From 21c97fb944638d6d8910893b056405f21c210991 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 3 May 2014 04:10:13 +0200
Subject: [PATCH] WIP VMware tools

---
 sys/conf/files                                     |    8 +
 sys/conf/kern.pre.mk                               |    3 +
 sys/config/LINT                                    |    7 +
 sys/config/LINT64                                  |    6 +
 sys/dev/virtual/Makefile                           |    2 +-
 sys/dev/virtual/vmware/Makefile                    |    3 +
 sys/dev/virtual/vmware/shared/backdoor_def.h       |  235 ++
 sys/dev/virtual/vmware/shared/backdoor_types.h     |  130 ++
 sys/dev/virtual/vmware/shared/circList.h           |  440 ++++
 sys/dev/virtual/vmware/shared/community_source.h   |   80 +
 sys/dev/virtual/vmware/shared/compat_freebsd.h     |   46 +
 sys/dev/virtual/vmware/shared/compat_mount.h       |   37 +
 sys/dev/virtual/vmware/shared/compat_priv.h        |   36 +
 sys/dev/virtual/vmware/shared/compat_vop.h         |   68 +
 sys/dev/virtual/vmware/shared/dbllnklst.h          |  302 +++
 sys/dev/virtual/vmware/shared/guest_msg_def.h      |  104 +
 sys/dev/virtual/vmware/shared/includeCheck.h       |  129 ++
 sys/dev/virtual/vmware/shared/vm_assert.h          |  354 +++
 sys/dev/virtual/vmware/shared/vm_atomic.h          | 2448 ++++++++++++++++++++
 sys/dev/virtual/vmware/shared/vm_basic_asm.h       | 1053 +++++++++
 sys/dev/virtual/vmware/shared/vm_basic_asm_x86.h   |  570 +++++
 .../virtual/vmware/shared/vm_basic_asm_x86_64.h    |  553 +++++
 sys/dev/virtual/vmware/shared/vm_basic_defs.h      |  660 ++++++
 sys/dev/virtual/vmware/shared/vm_basic_math.h      |   78 +
 sys/dev/virtual/vmware/shared/vm_basic_types.h     | 1004 ++++++++
 sys/dev/virtual/vmware/shared/vm_device_version.h  |  258 +++
 sys/dev/virtual/vmware/shared/vmware.h             |   69 +
 sys/dev/virtual/vmware/shared/vmware_pack_begin.h  |   55 +
 sys/dev/virtual/vmware/shared/vmware_pack_end.h    |   56 +
 sys/dev/virtual/vmware/shared/vmware_pack_init.h   |   77 +
 sys/dev/virtual/vmware/shared/x86cpuid.h           | 1165 ++++++++++
 sys/dev/virtual/vmware/shared/x86cpuid_asm.h       |  463 ++++
 sys/dev/virtual/vmware/vmblock/COPYING             |   24 +
 sys/dev/virtual/vmware/vmblock/Makefile            |    8 +
 sys/dev/virtual/vmware/vmblock/block.c             |  632 +++++
 sys/dev/virtual/vmware/vmblock/block.h             |   59 +
 sys/dev/virtual/vmware/vmblock/dbllnklst.c         |  210 ++
 sys/dev/virtual/vmware/vmblock/os.h                |  132 ++
 sys/dev/virtual/vmware/vmblock/os_panic.c          |   70 +
 sys/dev/virtual/vmware/vmblock/stubs.c             |   79 +
 sys/dev/virtual/vmware/vmblock/subr.c              |  488 ++++
 sys/dev/virtual/vmware/vmblock/vfsops.c            |  497 ++++
 sys/dev/virtual/vmware/vmblock/vmblock.h           |  178 ++
 sys/dev/virtual/vmware/vmblock/vmblock_k.h         |  151 ++
 sys/dev/virtual/vmware/vmblock/vnops.c             | 1542 ++++++++++++
 sys/gnu/Makefile                                   |    2 +-
 sys/gnu/dev/Makefile                               |    3 +
 sys/gnu/dev/virtual/Makefile                       |    3 +
 sys/gnu/dev/virtual/vmware/Makefile                |    3 +
 sys/gnu/dev/virtual/vmware/vmmemctl/COPYING        |  339 +++
 sys/gnu/dev/virtual/vmware/vmmemctl/Makefile       |   13 +
 sys/gnu/dev/virtual/vmware/vmmemctl/README         |   12 +
 sys/gnu/dev/virtual/vmware/vmmemctl/backdoor.h     |   46 +
 .../dev/virtual/vmware/vmmemctl/backdoorGcc32.c    |  220 ++
 .../dev/virtual/vmware/vmmemctl/backdoorGcc64.c    |  229 ++
 sys/gnu/dev/virtual/vmware/vmmemctl/backdoorInt.h  |   26 +
 .../dev/virtual/vmware/vmmemctl/backdoor_balloon.h |   39 +
 sys/gnu/dev/virtual/vmware/vmmemctl/balloon_def.h  |   83 +
 sys/gnu/dev/virtual/vmware/vmmemctl/dbllnklst.h    |  290 +++
 sys/gnu/dev/virtual/vmware/vmmemctl/os.c           |  757 ++++++
 sys/gnu/dev/virtual/vmware/vmmemctl/os.h           |   56 +
 sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.c    | 1240 ++++++++++
 sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.h    |   90 +
 sys/platform/pc32/Makefile.inc                     |    4 +-
 sys/platform/pc32/conf/files                       |    1 +
 sys/platform/pc64/Makefile.inc                     |    4 +-
 sys/platform/pc64/conf/files                       |    1 +
 67 files changed, 18024 insertions(+), 6 deletions(-)
 create mode 100644 sys/dev/virtual/vmware/Makefile
 create mode 100644 sys/dev/virtual/vmware/shared/backdoor_def.h
 create mode 100644 sys/dev/virtual/vmware/shared/backdoor_types.h
 create mode 100644 sys/dev/virtual/vmware/shared/circList.h
 create mode 100644 sys/dev/virtual/vmware/shared/community_source.h
 create mode 100644 sys/dev/virtual/vmware/shared/compat_freebsd.h
 create mode 100644 sys/dev/virtual/vmware/shared/compat_mount.h
 create mode 100644 sys/dev/virtual/vmware/shared/compat_priv.h
 create mode 100644 sys/dev/virtual/vmware/shared/compat_vop.h
 create mode 100644 sys/dev/virtual/vmware/shared/dbllnklst.h
 create mode 100644 sys/dev/virtual/vmware/shared/guest_msg_def.h
 create mode 100644 sys/dev/virtual/vmware/shared/includeCheck.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_assert.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_atomic.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_basic_asm.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_basic_asm_x86.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_basic_asm_x86_64.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_basic_defs.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_basic_math.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_basic_types.h
 create mode 100644 sys/dev/virtual/vmware/shared/vm_device_version.h
 create mode 100644 sys/dev/virtual/vmware/shared/vmware.h
 create mode 100644 sys/dev/virtual/vmware/shared/vmware_pack_begin.h
 create mode 100644 sys/dev/virtual/vmware/shared/vmware_pack_end.h
 create mode 100644 sys/dev/virtual/vmware/shared/vmware_pack_init.h
 create mode 100644 sys/dev/virtual/vmware/shared/x86cpuid.h
 create mode 100644 sys/dev/virtual/vmware/shared/x86cpuid_asm.h
 create mode 100644 sys/dev/virtual/vmware/vmblock/COPYING
 create mode 100644 sys/dev/virtual/vmware/vmblock/Makefile
 create mode 100644 sys/dev/virtual/vmware/vmblock/block.c
 create mode 100644 sys/dev/virtual/vmware/vmblock/block.h
 create mode 100644 sys/dev/virtual/vmware/vmblock/dbllnklst.c
 create mode 100644 sys/dev/virtual/vmware/vmblock/os.h
 create mode 100644 sys/dev/virtual/vmware/vmblock/os_panic.c
 create mode 100644 sys/dev/virtual/vmware/vmblock/stubs.c
 create mode 100644 sys/dev/virtual/vmware/vmblock/subr.c
 create mode 100644 sys/dev/virtual/vmware/vmblock/vfsops.c
 create mode 100644 sys/dev/virtual/vmware/vmblock/vmblock.h
 create mode 100644 sys/dev/virtual/vmware/vmblock/vmblock_k.h
 create mode 100644 sys/dev/virtual/vmware/vmblock/vnops.c
 create mode 100644 sys/gnu/dev/Makefile
 create mode 100644 sys/gnu/dev/virtual/Makefile
 create mode 100644 sys/gnu/dev/virtual/vmware/Makefile
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/COPYING
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/Makefile
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/README
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/backdoor.h
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc32.c
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc64.c
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/backdoorInt.h
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/backdoor_balloon.h
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/balloon_def.h
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/dbllnklst.h
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/os.c
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/os.h
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.c
 create mode 100644 sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.h

diff --git a/sys/conf/files b/sys/conf/files
index c63f083..f3b0a3b 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -869,6 +869,14 @@ dev/netif/rtw/smc93cx6.c		optional rtw
 dev/netif/rtw/if_rtw_pci.c		optional rtw pci
 dev/netif/xe/if_xe.c			optional xe
 dev/netif/xe/if_xe_pccard.c		optional xe pccard
+dev/virtual/vmware/vmblock/block.c	optional vmblock
+dev/virtual/vmware/vmblock/os_panic.c	optional vmblock
+dev/virtual/vmware/vmblock/stubs.c	optional vmblock
+dev/virtual/vmware/vmblock/subr.c	optional vmblock
+dev/virtual/vmware/vmblock/vnops.c	optional vmblock
+dev/virtual/vmware/vmblock/vfsops.c	optional vmblock
+gnu/dev/virtual/vmware/vmmemctl/os.c	optional vmmemctl
+gnu/dev/virtual/vmware/vmmemctl/vmballoon.c optional vmmemctl
 gnu/vfs/ext2fs/ext2_alloc.c		optional ext2fs
 gnu/vfs/ext2fs/ext2_balloc.c		optional ext2fs
 gnu/vfs/ext2fs/ext2_bmap.c		optional ext2fs
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 776639d..4e5e334 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -55,6 +55,9 @@ INCLUDES+= -I$S/dev/netif/ath/ath_hal -I$S/contrib/dev/ath/ath_hal
 # Same thing for drm includes
 INCLUDES+= -I$S/dev/drm/include
 
+# ... and VMware virtual devices shared files
+INCLUDES+= -I$S/dev/virtual/vmware/shared
+
 COPTS=	${INCLUDES} ${IDENT} -D_KERNEL -include opt_global.h
 CFLAGS=	${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS}
 
diff --git a/sys/config/LINT b/sys/config/LINT
index 830e9ca..b21474a 100644
--- a/sys/config/LINT
+++ b/sys/config/LINT
@@ -2363,6 +2363,13 @@ device		gpio		# Enable support for the gpio framework
 device		ichwd		# Intel ICH watchdog interrupt timer
 device		tbridge		# regression testing
 
+
+#
+# Virtual devices for VMware
+#
+device		vmblock
+device		vmmemctl
+
 #
 # VirtIO support
 #
diff --git a/sys/config/LINT64 b/sys/config/LINT64
index bbba035..d932508 100644
--- a/sys/config/LINT64
+++ b/sys/config/LINT64
@@ -2206,6 +2206,12 @@ device		vtnet
 device		virtio_pci
 
 #
+# Virtual devices for VMware
+#
+device		vmblock
+device		vmmemctl
+
+#
 # Embedded system options:
 #
 # An embedded system might want to run something other than init.
diff --git a/sys/dev/virtual/Makefile b/sys/dev/virtual/Makefile
index f1a4af8..abf0a56 100644
--- a/sys/dev/virtual/Makefile
+++ b/sys/dev/virtual/Makefile
@@ -1,6 +1,6 @@
 .include "${.CURDIR}/../../platform/${MACHINE_PLATFORM}/Makefile.inc"
 
-SUBDIR=	vkernel virtio
+SUBDIR=	vkernel virtio #vmware
 
 .for dir in ${SUBDIR}
 .if empty(DEV_SUPPORT:Mvirtual) && \
diff --git a/sys/dev/virtual/vmware/Makefile b/sys/dev/virtual/vmware/Makefile
new file mode 100644
index 0000000..6b7796d
--- /dev/null
+++ b/sys/dev/virtual/vmware/Makefile
@@ -0,0 +1,3 @@
+SUBDIR=	vmblock
+
+.include <bsd.subdir.mk>
diff --git a/sys/dev/virtual/vmware/shared/backdoor_def.h b/sys/dev/virtual/vmware/shared/backdoor_def.h
new file mode 100644
index 0000000..807d2f2
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/backdoor_def.h
@@ -0,0 +1,235 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * backdoor_def.h --
+ *
+ * This contains backdoor defines that can be included from
+ * an assembly language file.
+ */
+
+
+
+#ifndef _BACKDOOR_DEF_H_
+#define _BACKDOOR_DEF_H_
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_USERLEVEL
+
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMKERNEL
+#include "includeCheck.h"
+
+/*
+ * If you want to add a new low-level backdoor call for a guest userland
+ * application, please consider using the GuestRpc mechanism instead. --hpreg
+ */
+
+#define BDOOR_MAGIC 0x564D5868
+
+/* Low-bandwidth backdoor port. --hpreg */
+
+#define BDOOR_PORT 0x5658
+
+#define   BDOOR_CMD_GETMHZ      		    1
+/*
+ * BDOOR_CMD_APMFUNCTION is used by:
+ *
+ * o The FrobOS code, which instead should either program the virtual chipset
+ *   (like the new BIOS code does, matthias offered to implement that), or not
+ *   use any VM-specific code (which requires that we correctly implement
+ *   "power off on CLI HLT" for SMP VMs, boris offered to implement that)
+ *
+ * o The old BIOS code, which will soon be jettisoned
+ *
+ *  --hpreg
+ */
+#define   BDOOR_CMD_APMFUNCTION               2 /* CPL0 only. */
+#define   BDOOR_CMD_GETDISKGEO                3
+#define   BDOOR_CMD_GETPTRLOCATION            4
+#define   BDOOR_CMD_SETPTRLOCATION            5
+#define   BDOOR_CMD_GETSELLENGTH              6
+#define   BDOOR_CMD_GETNEXTPIECE              7
+#define   BDOOR_CMD_SETSELLENGTH              8
+#define   BDOOR_CMD_SETNEXTPIECE              9
+#define   BDOOR_CMD_GETVERSION               10
+#define   BDOOR_CMD_GETDEVICELISTELEMENT     11
+#define   BDOOR_CMD_TOGGLEDEVICE             12
+#define   BDOOR_CMD_GETGUIOPTIONS            13
+#define   BDOOR_CMD_SETGUIOPTIONS            14
+#define   BDOOR_CMD_GETSCREENSIZE            15
+#define   BDOOR_CMD_MONITOR_CONTROL          16 /* Disabled by default. */
+#define   BDOOR_CMD_GETHWVERSION             17
+#define   BDOOR_CMD_OSNOTFOUND               18 /* CPL0 only. */
+#define   BDOOR_CMD_GETUUID                  19
+#define   BDOOR_CMD_GETMEMSIZE               20
+#define   BDOOR_CMD_HOSTCOPY                 21 /* Devel only. */
+//#define BDOOR_CMD_SERVICE_VM               22 /* Not in use. Never shipped. */
+#define   BDOOR_CMD_GETTIME                  23 /* Deprecated -> GETTIMEFULL. */
+#define   BDOOR_CMD_STOPCATCHUP              24
+#define   BDOOR_CMD_PUTCHR                   25 /* Disabled by default. */
+#define   BDOOR_CMD_ENABLE_MSG               26 /* Devel only. */
+#define   BDOOR_CMD_GOTO_TCL                 27 /* Devel only. */
+#define   BDOOR_CMD_INITPCIOPROM             28 /* CPL 0 only. */
+//#define BDOOR_CMD_INT13                    29 /* Not in use. */
+#define   BDOOR_CMD_MESSAGE                  30
+#define   BDOOR_CMD_SIDT                     31
+#define   BDOOR_CMD_SGDT                     32
+#define   BDOOR_CMD_SLDT_STR                 33
+#define   BDOOR_CMD_ISACPIDISABLED           34
+//#define BDOOR_CMD_TOE                      35 /* Not in use. */
+#define   BDOOR_CMD_ISMOUSEABSOLUTE          36
+#define   BDOOR_CMD_PATCH_SMBIOS_STRUCTS     37 /* CPL 0 only. */
+#define   BDOOR_CMD_MAPMEM                   38 /* Devel only */
+#define   BDOOR_CMD_ABSPOINTER_DATA          39
+#define   BDOOR_CMD_ABSPOINTER_STATUS        40
+#define   BDOOR_CMD_ABSPOINTER_COMMAND       41
+//#define BDOOR_CMD_TIMER_SPONGE             42 /* Not in use. */
+#define   BDOOR_CMD_PATCH_ACPI_TABLES        43 /* CPL 0 only. */
+//#define BDOOR_CMD_DEVEL_FAKEHARDWARE       44 /* Not in use. */
+#define   BDOOR_CMD_GETHZ                    45
+#define   BDOOR_CMD_GETTIMEFULL              46
+#define   BDOOR_CMD_STATELOGGER              47 /* Disabled by default. */
+#define   BDOOR_CMD_CHECKFORCEBIOSSETUP      48 /* CPL 0 only. */
+#define   BDOOR_CMD_LAZYTIMEREMULATION       49 /* CPL 0 only. */
+#define   BDOOR_CMD_BIOSBBS                  50 /* CPL 0 only. */
+//#define BDOOR_CMD_VASSERT                  51 /* Not in use. */
+#define   BDOOR_CMD_ISGOSDARWIN              52
+#define   BDOOR_CMD_DEBUGEVENT               53
+#define   BDOOR_CMD_OSNOTMACOSXSERVER        54 /* CPL 0 only. */
+#define   BDOOR_CMD_GETTIMEFULL_WITH_LAG     55
+#define   BDOOR_CMD_ACPI_HOTPLUG_DEVICE      56 /* Devel only. */
+#define   BDOOR_CMD_ACPI_HOTPLUG_MEMORY      57 /* Devel only. */
+#define   BDOOR_CMD_ACPI_HOTPLUG_CBRET       58 /* Devel only. */
+//#define BDOOR_CMD_GET_HOST_VIDEO_MODES     59 /* Not in use. */
+#define   BDOOR_CMD_ACPI_HOTPLUG_CPU         60 /* Devel only. */
+//#define BDOOR_CMD_USB_HOTPLUG_MOUSE        61 /* Not in use. Never shipped. */
+#define   BDOOR_CMD_XPMODE                   62 /* CPL 0 only. */
+#define   BDOOR_CMD_NESTING_CONTROL          63
+#define   BDOOR_CMD_FIRMWARE_INIT            64 /* CPL 0 only. */
+#define   BDOOR_CMD_FIRMWARE_ACPI_SERVICES   65 /* CPL 0 only. */
+#  define BDOOR_CMD_FAS_GET_TABLE_SIZE        0
+#  define BDOOR_CMD_FAS_GET_TABLE_DATA        1
+#  define BDOOR_CMD_FAS_GET_PLATFORM_NAME     2
+#  define BDOOR_CMD_FAS_GET_PCIE_OSC_MASK     3
+#define   BDOOR_CMD_SENDPSHAREHINTS          66
+#define   BDOOR_CMD_ENABLE_USB_MOUSE         67
+#define   BDOOR_CMD_GET_VCPU_INFO            68
+#  define BDOOR_CMD_VCPU_SLC64                0
+#  define BDOOR_CMD_VCPU_SYNC_VTSCS           1
+#  define BDOOR_CMD_VCPU_HV_REPLAY_OK         2
+#  define BDOOR_CMD_VCPU_RESERVED            31
+#define   BDOOR_CMD_EFI_SERIALCON_CONFIG     69 /* CPL 0 only. */
+#define   BDOOR_CMD_BUG328986                70 /* CPL 0 only. */
+#define   BDOOR_CMD_FIRMWARE_ERROR           71 /* CPL 0 only. */
+#  define BDOOR_CMD_FE_INSUFFICIENT_MEM       0
+#  define BDOOR_CMD_FE_EXCEPTION              1
+#define   BDOOR_CMD_MAX                      72
+
+
+/*
+ * IMPORTANT NOTE: When modifying the behavior of an existing backdoor command,
+ * you must adhere to the semantics expected by the oldest Tools who use that
+ * command. Specifically, do not alter the way in which the command modifies
+ * the registers. Otherwise backwards compatibility will suffer.
+ */
+
+/* Processing mode for guest pshare hints (SENDPSHAREHINTS cmd) */
+#define BDOOR_PSHARE_HINTS_ASYNC 0
+#define BDOOR_PSHARE_HINTS_SYNC  1
+
+#define BDOOR_PSHARE_HINTS_TYPE(ecx)   (((ecx) >> 16) & 0x1)
+
+/* Version of backdoor pshare hints protocol */
+#define BDOOR_PSHARE_HINTS_VERSION     1
+#define BDOOR_PSHARE_HINTS_VER(ecx)    (((ecx) >> 17) & 0x7f)
+
+/* Task applied to backdoor pshare hints */
+#define BDOOR_PSHARE_HINTS_CMD_SHARE   0
+#define BDOOR_PSHARE_HINTS_CMD_DROP    1
+
+#define BDOOR_PSHARE_HINTS_CMD(ecx)   (((ecx) >> 24) & 0x1)
+
+/* Nesting control operations */
+
+#define NESTING_CONTROL_RESTRICT_BACKDOOR 0
+#define NESTING_CONTROL_OPEN_BACKDOOR     1
+#define NESTING_CONTROL_QUERY             2
+#define NESTING_CONTROL_MAX               2
+
+/* High-bandwidth backdoor port. --hpreg */
+
+#define BDOORHB_PORT 0x5659
+
+#define BDOORHB_CMD_MESSAGE 0
+#define BDOORHB_CMD_VASSERT 1
+#define BDOORHB_CMD_MAX 2
+
+/*
+ * There is another backdoor which allows access to certain TSC-related
+ * values using otherwise illegal PMC indices when the pseudo_perfctr
+ * control flag is set.
+ */
+
+#define BDOOR_PMC_HW_TSC      0x10000
+#define BDOOR_PMC_REAL_NS     0x10001
+#define BDOOR_PMC_APPARENT_NS 0x10002
+#define BDOOR_PMC_PSEUDO_TSC  0x10003
+
+#define IS_BDOOR_PMC(index)  (((index) | 3) == 0x10003)
+#define BDOOR_CMD(ecx)       ((ecx) & 0xffff)
+
+
+#ifdef VMM
+/*
+ *----------------------------------------------------------------------
+ *
+ * Backdoor_CmdRequiresFullyValidVCPU --
+ *
+ *    A few backdoor commands require the full VCPU to be valid
+ *    (including GDTR, IDTR, TR and LDTR). The rest get read/write
+ *    access to GPRs and read access to Segment registers (selectors).
+ *
+ * Result:
+ *    True iff VECX contains a command that require the full VCPU to
+ *    be valid.
+ *
+ *----------------------------------------------------------------------
+ */
+static INLINE Bool
+Backdoor_CmdRequiresFullyValidVCPU(unsigned cmd)
+{
+   return cmd == BDOOR_CMD_SIDT ||
+          cmd == BDOOR_CMD_SGDT ||
+          cmd == BDOOR_CMD_SLDT_STR;
+}
+#endif
+
+#endif
diff --git a/sys/dev/virtual/vmware/shared/backdoor_types.h b/sys/dev/virtual/vmware/shared/backdoor_types.h
new file mode 100644
index 0000000..e985f13
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/backdoor_types.h
@@ -0,0 +1,130 @@
+/*********************************************************
+ * Copyright (C) 1999 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * backdoor_types.h --
+ *
+ *    Type definitions for backdoor interaction code.
+ */
+
+#ifndef _BACKDOOR_TYPES_H_
+#define _BACKDOOR_TYPES_H_
+
+#ifndef VM_I386
+#error The backdoor protocol is only supported on x86 architectures.
+#endif
+
+/*
+ * These #defines are intended for defining register structs as part of
+ * existing named unions. If the union should encapsulate the register
+ * (and nothing else), use DECLARE_REG_NAMED_STRUCT defined below.
+ */
+
+#define DECLARE_REG32_STRUCT \
+   struct { \
+      uint16 low; \
+      uint16 high; \
+   } halfs; \
+   uint32 word
+
+#define DECLARE_REG64_STRUCT \
+   DECLARE_REG32_STRUCT; \
+   struct { \
+      uint32 low; \
+      uint32 high; \
+   } words; \
+   uint64 quad
+
+#ifndef VM_X86_64
+#define DECLARE_REG_STRUCT DECLARE_REG32_STRUCT
+#else
+#define DECLARE_REG_STRUCT DECLARE_REG64_STRUCT
+#endif
+
+#define DECLARE_REG_NAMED_STRUCT(_r) \
+   union { DECLARE_REG_STRUCT; } _r
+
+/*
+ * Some of the registers are expressed by semantic name, because if they were
+ * expressed as register structs declared above, we could only address them
+ * by fixed size (half-word, word, quad, etc.) instead of by varying size
+ * (size_t, uintptr_t).
+ *
+ * To be cleaner, these registers are expressed ONLY by semantic name,
+ * rather than by a union of the semantic name and a register struct.
+ */
+typedef union {
+   struct {
+      DECLARE_REG_NAMED_STRUCT(ax);
+      size_t size; /* Register bx. */
+      DECLARE_REG_NAMED_STRUCT(cx);
+      DECLARE_REG_NAMED_STRUCT(dx);
+      DECLARE_REG_NAMED_STRUCT(si);
+      DECLARE_REG_NAMED_STRUCT(di);
+   } in;
+   struct {
+      DECLARE_REG_NAMED_STRUCT(ax);
+      DECLARE_REG_NAMED_STRUCT(bx);
+      DECLARE_REG_NAMED_STRUCT(cx);
+      DECLARE_REG_NAMED_STRUCT(dx);
+      DECLARE_REG_NAMED_STRUCT(si);
+      DECLARE_REG_NAMED_STRUCT(di);
+   } out;
+} Backdoor_proto;
+
+typedef union {
+   struct {
+      DECLARE_REG_NAMED_STRUCT(ax);
+      DECLARE_REG_NAMED_STRUCT(bx);
+      size_t size; /* Register cx. */
+      DECLARE_REG_NAMED_STRUCT(dx);
+      uintptr_t srcAddr; /* Register si. */
+      uintptr_t dstAddr; /* Register di. */
+      DECLARE_REG_NAMED_STRUCT(bp);
+   } in;
+   struct {
+      DECLARE_REG_NAMED_STRUCT(ax);
+      DECLARE_REG_NAMED_STRUCT(bx);
+      DECLARE_REG_NAMED_STRUCT(cx);
+      DECLARE_REG_NAMED_STRUCT(dx);
+      DECLARE_REG_NAMED_STRUCT(si);
+      DECLARE_REG_NAMED_STRUCT(di);
+      DECLARE_REG_NAMED_STRUCT(bp);
+   } out;
+} Backdoor_proto_hb;
+
+MY_ASSERTS(BACKDOOR_STRUCT_SIZES,
+           ASSERT_ON_COMPILE(sizeof(Backdoor_proto) == 6 * sizeof(uintptr_t));
+           ASSERT_ON_COMPILE(sizeof(Backdoor_proto_hb) == 7 * sizeof(uintptr_t));
+)
+
+#undef DECLARE_REG_STRUCT
+
+#endif /* _BACKDOOR_TYPES_H_ */
diff --git a/sys/dev/virtual/vmware/shared/circList.h b/sys/dev/virtual/vmware/shared/circList.h
new file mode 100644
index 0000000..d6e134b
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/circList.h
@@ -0,0 +1,440 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ *   circList.h --
+ *
+ * macros, prototypes and struct definitions for double-linked
+ * circular lists.
+ */
+
+#ifndef _CIRCLIST_H_
+#define _CIRCLIST_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#include "includeCheck.h"
+#include "vmware.h"
+
+typedef struct ListItem {
+   struct ListItem *prev;
+   struct ListItem *next;
+} ListItem;
+
+/* A list with no elements is a null pointer. */
+#define   LIST_ITEM_DEF(name)   \
+   ListItem * name = NULL
+
+#define   LIST_EMPTY(l)      ((l) == NULL)
+
+/* initialize list item */
+#define   INIT_LIST_ITEM(p)   \
+   do {   \
+      (p)->prev = (p)->next = (p);   \
+   } while (0)
+
+/* check if initialized */
+#define   IS_LIST_ITEM_INITIALIZED(li)   \
+   (((li) == (li)->prev) && ((li) == (li)->next))
+
+/* return first element in the list */
+#define   LIST_FIRST(l)      (l)
+#define   LIST_FIRST_CHK(l)   (l)
+
+/* return last element in the list */
+#define   LIST_LAST(l)      ((l)->prev)
+#define   LIST_LAST_CHK(l)   (LIST_EMPTY(l) ? NULL : LIST_LAST(l))
+
+/*
+ * LIST_CONTAINER - get the struct for this entry (like list_entry)
+ * @ptr: the &struct ListItem pointer.
+ * @type:   the type of the struct this is embedded in.
+ * @member: the name of the list struct within the struct.
+ */
+#define LIST_CONTAINER(ptr, type, member) \
+   ((type *)((char *)(ptr) - offsetof(type, member)))
+
+/*
+ * delete item from the list
+ */
+#define   LIST_DEL            DelListItem
+
+/*
+ * link two lists together
+ */
+#define   LIST_SPLICE         SpliceLists
+
+/*
+ * Split a list into two lists
+ */
+#define   LIST_SPLIT          SplitLists
+
+/*
+ * Add item to front of stack. List pointer points to new head.
+ */
+#define   LIST_PUSH           PushListItem
+
+/*
+ * Add item at back of queue. List pointer only changes if list was empty.
+ */
+#define   LIST_QUEUE          QueueListItem
+
+/*
+ * Get the list size.
+ */
+#define   LIST_SIZE           GetListSize
+
+/*
+ * LIST_SCAN_FROM scans the list from "from" up until "until".
+ * The loop variable p should not be destroyed in the process.
+ * "from" is an element in the list where to start scanning.
+ * "until" is the element where search should stop.
+ * member is the field to use for the search - either "next" or "prev".
+ */
+#define   LIST_SCAN_FROM(p, from, until, member)   \
+   for (p = (from); (p) != NULL;   \
+      (p) = (((p)->member == (until)) ? NULL : (p)->member))
+
+/* scan the entire list (non-destructively) */
+#define   LIST_SCAN(p, l)   \
+   LIST_SCAN_FROM(p, LIST_FIRST(l), LIST_FIRST(l), next)
+
+
+/* scan a list backward from last element to first (non-destructively) */
+#define   LIST_SCAN_BACK(p, l)   \
+   LIST_SCAN_FROM(p, LIST_LAST_CHK(l), LIST_LAST(l), prev)
+
+/* scan the entire list where loop element may be destroyed */
+#define   LIST_SCAN_SAFE(p, pn, l)   \
+   if (!LIST_EMPTY(l))  \
+      for (p = (l), (pn) = NextListItem(p, l); (p) != NULL;   \
+           (p) = (pn), (pn) = NextListItem(p, l))
+
+/* scan the entire list backwards where loop element may be destroyed */
+#define   LIST_SCAN_BACK_SAFE(p, pn, l)   \
+   if (!LIST_EMPTY(l))  \
+      for (p = LIST_LAST(l), (pn) = PrevListItem(p, l); (p) != NULL;   \
+           (p) = (pn), (pn) = PrevListItem(p, l))
+
+
+/* function definitions */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NextListItem --
+ *
+ *      Returns the next member of a doubly linked list, or NULL if last.
+ *      Assumes: p is member of the list headed by head.
+ *
+ * Result:
+ *      If head or p is NULL, return NULL. Otherwise,
+ *      next list member (or null if last).
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE ListItem *
+NextListItem(ListItem *p,        // IN
+             ListItem *head)     // IN
+{
+   if (head == NULL || p == NULL) {
+      return NULL;
+   }
+   /* both p and head are non-null */
+   p = p->next;
+   return p == head ? NULL : p;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PrevListItem --
+ *
+ *      Returns the prev member of a doubly linked list, or NULL if first.
+ *      Assumes: p is member of the list headed by head.
+ *
+ * Result:
+ *      If head or prev is NULL, return NULL. Otherwise,
+ *      prev list member (or null if first).
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE ListItem *
+PrevListItem(ListItem *p,        // IN
+             ListItem *head)     // IN
+{
+   if (head == NULL || p == NULL) {
+      return NULL;
+   }
+   /* both p and head are non-null */
+   return p == head ? NULL : p->prev;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DelListItem --
+ *
+ *      Deletes a member of a doubly linked list, possibly modifies the
+ *      list header itself.
+ *      Assumes neither p nor headp is null and p is a member of *headp.
+ *
+ * Result:
+ *      None
+ *
+ * Side effects:
+ *      Modifies *headp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DelListItem(ListItem *p,         // IN
+            ListItem **headp)    // IN/OUT
+{
+   ListItem *next;
+
+   ASSERT(p);
+   ASSERT(headp);
+
+   next = p->next;
+   if (p == next) {
+      *headp = NULL;
+   } else {
+      next->prev = p->prev;
+      p->prev->next = next;
+      if (*headp == p) {
+         *headp = next;
+      }
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * QueueListItem --
+ *
+ *      Adds a new member to the back of a doubly linked list (queue)
+ *      Assumes neither p nor headp is null and p is not a member of *headp.
+ *
+ * Result:
+ *      None
+ *
+ * Side effects:
+ *      Modifies *headp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+QueueListItem(ListItem *p,              // IN
+              ListItem **headp)         // IN/OUT
+{
+   ListItem *head;
+
+   head = *headp;
+   if (LIST_EMPTY(head)) {
+      INIT_LIST_ITEM(p);
+      *headp = p;
+   } else {
+      p->prev = head->prev;
+      p->next = head;
+      p->prev->next = p;
+      head->prev = p;
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PushListItem --
+ *
+ *      Adds a new member to the front of a doubly linked list (stack)
+ *      Assumes neither p nor headp is null and p is not a member of *headp.
+ *
+ * Result:
+ *      None
+ *
+ * Side effects:
+ *      Modifies *headp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+PushListItem(ListItem *p,               // IN
+             ListItem **headp)          // IN/OUT
+{
+   QueueListItem(p, headp);
+   *headp = p;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SpliceLists --
+ *
+ *      Make a single list {l1 l2} from {l1} and {l2} and return it.
+ *      It is okay for one or both lists to be NULL.
+ *      No checking is done. It is assumed that l1 and l2 are two
+ *      distinct lists.
+ *
+ * Result:
+ *      A list { l1 l2 }.
+ *
+ * Side effects:
+ *      Modifies l1 and l2 list pointers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE ListItem *
+SpliceLists(ListItem *l1,      // IN
+            ListItem *l2)      // IN
+{
+   ListItem *l1Last, *l2Last;
+
+   if (LIST_EMPTY(l1)) {
+      return l2;
+   }
+
+   if (LIST_EMPTY(l2)) {
+      return l1;
+   }
+
+   l1Last = l1->prev;   /* last elem of l1 */
+   l2Last = l2->prev;   /* last elem of l2 */
+
+   /*
+    *    l1 -> ... -> l1Last    l2 -> ... l2Last
+    */
+   l1Last->next = l2;
+   l2->prev = l1Last;
+
+   l1->prev = l2Last;
+   l2Last->next = l1;
+
+   return l1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SplitLists --
+ *
+ *      Make a list l = {l1 l2} into two separate lists {l1} and {l2}, where:
+ *      l = { ... x -> p -> ... } split into:
+ *      l1 = { ... -> x }
+ *      l2 = { p -> ... }
+ *      Assumes neither p nor l is null and p is a member of l.
+ *      If p is the first element of l, then l1 will be NULL.
+ *
+ * Result:
+ *      None.
+ *
+ * Side effects:
+ *      Sets *l1p and *l2p to the resulting two lists.
+ *      Modifies l's pointers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+SplitLists(ListItem *p,         // IN
+           ListItem *l,         // IN
+           ListItem **l1p,      // OUT
+           ListItem **l2p)      // OUT
+{
+   ListItem *last;
+
+   if (p == LIST_FIRST(l)) {   /* first element */
+      *l1p = NULL;
+      *l2p = l;
+      return;
+   }
+
+   last = l->prev;
+
+   *l1p = l;
+   p->prev->next = l;
+   l->prev = p->prev;
+
+   *l2p = p;
+   p->prev = last;
+   last->next = p;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetListSize --
+ *
+ *	Return the number of items in the list.
+ *
+ * Result:
+ *	The number of items in the list.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE int
+GetListSize(ListItem *head)     // IN
+{
+   ListItem *li;
+   int ret = 0;
+
+   LIST_SCAN(li, head) {
+      ret++;
+   }
+   return ret;
+}
+
+#endif /* _CIRCLIST_H_ */
diff --git a/sys/dev/virtual/vmware/shared/community_source.h b/sys/dev/virtual/vmware/shared/community_source.h
new file mode 100644
index 0000000..71b131e
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/community_source.h
@@ -0,0 +1,80 @@
+/*********************************************************
+ * Copyright (C) 2009 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
+#define INCLUDE_ALLOW_VMIROM
+#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
diff --git a/sys/dev/virtual/vmware/shared/compat_freebsd.h b/sys/dev/virtual/vmware/shared/compat_freebsd.h
new file mode 100644
index 0000000..7e45306
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/compat_freebsd.h
@@ -0,0 +1,46 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_FREEBSD_H__
+#define __COMPAT_FREEBSD_H__ 1
+
+#include <sys/param.h>
+#include "compat_vop.h"
+#include "compat_mount.h"
+#include "compat_priv.h"
+
+/*
+ * FreeBSD version 8 and above uses the kproc API instead of the kthread API in its
+ * kernel.
+ */
+#define compat_kthread_create kthread_create
+#define compat_kthread_exit kthread_exit
+
+#endif // __COMPAT_FREEBSD_H__
diff --git a/sys/dev/virtual/vmware/shared/compat_mount.h b/sys/dev/virtual/vmware/shared/compat_mount.h
new file mode 100644
index 0000000..2c48df9
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/compat_mount.h
@@ -0,0 +1,37 @@
+/*********************************************************
+ * Copyright (C) 2009 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_MOUNT_H__
+#   define __COMPAT_MOUNT_H__ 1
+
+#define COMPAT_VFS_STATFS(mp, sbp, cred) VFS_STATFS((mp), (sbp), (cred))
+#define compat_td curthread
+
+#endif
diff --git a/sys/dev/virtual/vmware/shared/compat_priv.h b/sys/dev/virtual/vmware/shared/compat_priv.h
new file mode 100644
index 0000000..5e51c65
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/compat_priv.h
@@ -0,0 +1,36 @@
+/*********************************************************
+ * Copyright (C) 2009 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_PRIV_H__
+#   define __COMPAT_PRIV_H__ 1
+
+#define compat_priv_check(td, priv) priv_check((td), (priv))
+
+#endif
diff --git a/sys/dev/virtual/vmware/shared/compat_vop.h b/sys/dev/virtual/vmware/shared/compat_vop.h
new file mode 100644
index 0000000..4135e65
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/compat_vop.h
@@ -0,0 +1,68 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_VOP_H__
+#   define __COMPAT_VOP_H__ 1
+
+#ifdef __DragonFly__ //__FreeBSD_version >= 800011
+#define COMPAT_THREAD_VAR(varname, varval)
+#define COMPAT_VOP_LOCK(vop, flags, threadvar) VOP_LOCK((vop), (flags))
+#define COMPAT_VOP_UNLOCK(vop, flags, threadvar) VOP_UNLOCK((vop), (flags))
+#define compat_lockstatus(lock, threadvar) lockstatus((lock))
+#define compat_lockmgr(lock, flags, randompointerparam, threadval) lockmgr((lock), (flags))
+#define compat_vn_lock(vp, flags, threadval) vn_lock((vp), (flags))
+#define compat_accmode_t accmode_t
+#define compat_a_accmode a_accmode
+#else
+#define COMPAT_THREAD_VAR(varname, varval) struct thread *varname = varval
+#define COMPAT_VOP_LOCK(vop, flags, threadvar) VOP_LOCK((vop), (flags), (threadvar))
+#define COMPAT_VOP_UNLOCK(vop, flags, threadvar) VOP_UNLOCK((vop), (flags), (threadvar))
+#define compat_lockstatus(lock, threadvar) lockstatus((lock), (threadvar))
+#define compat_vn_lock(vp, flags, threadval) vn_lock((vp), (flags), (threadval))
+#define compat_lockmgr(lock, flags, randompointerparam, threadval) lockmgr((lock), (flags), (randompointerparam), (threadval))
+#define compat_accmode_t mode_t
+#define compat_a_accmode a_mode
+#endif
+
+/*
+ * We use defines rather than typedefs here to avoid causing problems for files that
+ * don't have a vnode_if.h available.
+ */
+#if __FreeBSD_version >= 700055
+#   define compat_vop_lock_t vop_lock1_t
+#   define compat_vop_lock_args struct vop_lock1_args
+#   define COMPAT_VOP_LOCK_OP_ELEMENT vop_lock1
+#else
+#   define compat_vop_lock_t vop_lock_t
+#   define compat_vop_lock_args struct vop_lock_args
+#   define COMPAT_VOP_LOCK_OP_ELEMENT vop_lock
+#endif
+
+#endif
diff --git a/sys/dev/virtual/vmware/shared/dbllnklst.h b/sys/dev/virtual/vmware/shared/dbllnklst.h
new file mode 100644
index 0000000..319b14a
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/dbllnklst.h
@@ -0,0 +1,302 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * dbllnklst.h --
+ *
+ *    Double linked lists
+ */
+
+#ifndef _DBLLNKLST_H_
+#define _DBLLNKLST_H_
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_USERLEVEL
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+#define DblLnkLst_OffsetOf(type, field) ((intptr_t)&((type *)0)->field)
+
+#define DblLnkLst_Container(addr, type, field) \
+   ((type *)((char *)(addr) - DblLnkLst_OffsetOf(type, field)))
+
+#define DblLnkLst_ForEach(curr, head)                   \
+      for (curr = (head)->next; curr != (head); curr = (curr)->next)
+
+/* Safe from list element removal within loop body. */
+#define DblLnkLst_ForEachSafe(curr, nextElem, head)             \
+      for (curr = (head)->next, nextElem = (curr)->next;        \
+           curr != (head);                                      \
+           curr = nextElem, nextElem = (curr)->next)
+
+typedef struct DblLnkLst_Links {
+   struct DblLnkLst_Links *prev;
+   struct DblLnkLst_Links *next;
+} DblLnkLst_Links;
+
+
+/*
+ * Functions
+ *
+ * DblLnkLst_LinkFirst, DblLnkLst_LinkLast, and DblLnkLst_Swap are specific
+ * to anchored lists.  The rest are for both circular and anchored lists.
+ */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Init --
+ *
+ *    Initialize a member of a doubly linked list
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Init(DblLnkLst_Links *l) // IN
+{
+   l->prev = l->next = l;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Link --
+ *
+ *    Merge two doubly linked lists into one
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is DblLnkLst_Unlink)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Link(DblLnkLst_Links *l1, // IN
+               DblLnkLst_Links *l2) // IN
+{
+   DblLnkLst_Links *tmp;
+
+   (tmp      = l1->prev)->next = l2;
+   (l1->prev = l2->prev)->next = l1;
+    l2->prev = tmp                 ;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Unlink --
+ *
+ *    Split one doubly linked list into two
+ *
+ *    No check is performed: the caller must ensure that both members
+ *    belong to the same doubly linked list
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is DblLnkLst_Link)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
+                 DblLnkLst_Links *l2) // IN
+{
+   DblLnkLst_Links *tmp;
+
+   tmp       = l1->prev            ;
+   (l1->prev = l2->prev)->next = l1;
+   (l2->prev = tmp     )->next = l2;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Unlink1 --
+ *
+ *    Unlink an element from its list.
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
+{
+   DblLnkLst_Unlink(l, l->next);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * DblLnkLst_IsLinked --
+ *
+ *    Determines whether an element is linked with any other elements.
+ *
+ * Results:
+ *    TRUE if link is linked, FALSE otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+DblLnkLst_IsLinked(DblLnkLst_Links const *l) // IN
+{
+   /*
+    * A DblLnkLst_Links is either linked to itself (not linked) or linked to
+    * other elements in a list (linked).
+    */
+   return l->prev != l;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_LinkFirst --
+ *
+ *    Insert 'l' at the beginning of the list anchored at 'head'
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
+                    DblLnkLst_Links *l)    // IN
+{
+   DblLnkLst_Link(head->next, l);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_LinkLast --
+ *
+ *    Insert 'l' at the end of the list anchored at 'head'
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
+                   DblLnkLst_Links *l)    // IN
+{
+   DblLnkLst_Link(head, l);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Swap --
+ *
+ *    Swap all entries between the list anchored at 'head1' and the list
+ *    anchored at 'head2'.
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is itself)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Swap(DblLnkLst_Links *head1,  // IN/OUT
+               DblLnkLst_Links *head2)  // IN/OUT
+{
+   DblLnkLst_Links const tmp = *head1;
+
+   if (DblLnkLst_IsLinked(head2)) {
+      (head1->prev = head2->prev)->next = head1;
+      (head1->next = head2->next)->prev = head1;
+   } else {
+      DblLnkLst_Init(head1);
+   }
+
+   if (tmp.prev != head1) {
+      (head2->prev = tmp.prev)->next = head2;
+      (head2->next = tmp.next)->prev = head2;
+   } else {
+      DblLnkLst_Init(head2);
+   }
+}
+
+
+#endif /* _DBLLNKLST_H_ */
diff --git a/sys/dev/virtual/vmware/shared/guest_msg_def.h b/sys/dev/virtual/vmware/shared/guest_msg_def.h
new file mode 100644
index 0000000..b062ca1
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/guest_msg_def.h
@@ -0,0 +1,104 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * guest_msg_def.h --
+ *
+ *    Second layer of the internal communication channel between guest
+ *    applications and vmware
+ *
+ */
+
+#ifndef _GUEST_MSG_DEF_H_
+#define _GUEST_MSG_DEF_H_
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_USERLEVEL
+
+#include "includeCheck.h"
+
+
+/* Basic request types */
+typedef enum {
+   MESSAGE_TYPE_OPEN,
+   MESSAGE_TYPE_SENDSIZE,
+   MESSAGE_TYPE_SENDPAYLOAD,
+   MESSAGE_TYPE_RECVSIZE,
+   MESSAGE_TYPE_RECVPAYLOAD,
+   MESSAGE_TYPE_RECVSTATUS,
+   MESSAGE_TYPE_CLOSE,
+} MessageType;
+
+
+/* Reply statuses */
+/*  The basic request succeeded */
+#define MESSAGE_STATUS_SUCCESS  0x0001
+/*  vmware has a message available for its party */
+#define MESSAGE_STATUS_DORECV   0x0002
+/*  The channel has been closed */
+#define MESSAGE_STATUS_CLOSED   0x0004
+/*  vmware removed the message before the party fetched it */
+#define MESSAGE_STATUS_UNSENT   0x0008
+/*  A checkpoint occurred */
+#define MESSAGE_STATUS_CPT      0x0010
+/*  An underlying device is powering off */
+#define MESSAGE_STATUS_POWEROFF 0x0020
+/*  vmware has detected a timeout on the channel */
+#define MESSAGE_STATUS_TIMEOUT  0x0040
+/*  vmware supports high-bandwidth for sending and receiving the payload */
+#define MESSAGE_STATUS_HB       0x0080
+
+/*
+ * This mask defines the status bits that the guest is allowed to set;
+ * we use this to mask out all other bits when receiving the status
+ * from the guest. Otherwise, the guest can manipulate VMX state by
+ * setting status bits that are only supposed to be changed by the
+ * VMX. See bug 45385.
+ */
+#define MESSAGE_STATUS_GUEST_MASK    MESSAGE_STATUS_SUCCESS
+
+/*
+ * Max number of channels.
+ * Unfortunately this has to be public because the monitor part
+ * of the backdoor needs it for its trivial-case optimization. [greg]
+ */
+#define GUESTMSG_MAX_CHANNEL 8
+
+/* Flags to open a channel. --hpreg */
+#define GUESTMSG_FLAG_COOKIE 0x80000000
+#define GUESTMSG_FLAG_ALL GUESTMSG_FLAG_COOKIE
+
+/*
+ * Maximum size of incoming message. This is to prevent denial of host service
+ * attacks from guest applications.
+ */
+#define GUESTMSG_MAX_IN_SIZE (64 * 1024)
+
+#endif /* _GUEST_MSG_DEF_H_ */
diff --git a/sys/dev/virtual/vmware/shared/includeCheck.h b/sys/dev/virtual/vmware/shared/includeCheck.h
new file mode 100644
index 0000000..6b2ee65
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/includeCheck.h
@@ -0,0 +1,129 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * includeCheck.h --
+ *
+ *	Restrict include file use.
+ *
+ * In every .h file, define one or more of these
+ *
+ *	INCLUDE_ALLOW_VMX
+ *	INCLUDE_ALLOW_USERLEVEL
+ *	INCLUDE_ALLOW_VMCORE
+ *	INCLUDE_ALLOW_MODULE
+ *	INCLUDE_ALLOW_VMKERNEL
+ *	INCLUDE_ALLOW_DISTRIBUTE
+ *	INCLUDE_ALLOW_VMK_MODULE
+ *      INCLUDE_ALLOW_VMKDRIVERS
+ *      INCLUDE_ALLOW_VMIROM
+ *
+ * Then include this file.
+ *
+ * Any file that has INCLUDE_ALLOW_DISTRIBUTE defined will potentially
+ * be distributed in source form along with GPLed code.  Ensure
+ * that this is acceptable.
+ */
+
+
+/*
+ * Declare a VMCORE-only variable to help classify object
+ * files.  The variable goes in the common block and does
+ * not create multiple definition link-time conflicts.
+ */
+
+#if defined VMCORE && defined VMX86_DEVEL && defined VMX86_DEBUG && \
+    defined linux && !defined MODULE && \
+    !defined COMPILED_WITH_VMCORE
+#define COMPILED_WITH_VMCORE compiled_with_vmcore
+#ifdef ASM
+        .comm   compiled_with_vmcore, 0
+#else
+        asm(".comm compiled_with_vmcore, 0");
+#endif /* ASM */
+#endif
+
+
+#if defined VMCORE && \
+    !(defined VMX86_VMX || defined VMM || \
+      defined MONITOR_APP || defined VMMON)
+#error "Makefile problem: VMCORE without VMX86_VMX or \
+        VMM or MONITOR_APP or MODULE."
+#endif
+
+#if defined VMCORE && !defined INCLUDE_ALLOW_VMCORE
+#error "The surrounding include file is not allowed in vmcore."
+#endif
+#undef INCLUDE_ALLOW_VMCORE
+
+#if defined VMX86_VMX && !defined VMCORE && \
+    !(defined INCLUDE_ALLOW_VMX || defined INCLUDE_ALLOW_USERLEVEL)
+#error "The surrounding include file is not allowed in the VMX."
+#endif
+#undef INCLUDE_ALLOW_VMX
+
+#if defined USERLEVEL && !defined VMX86_VMX && !defined VMCORE && \
+    !defined INCLUDE_ALLOW_USERLEVEL
+#error "The surrounding include file is not allowed at userlevel."
+#endif
+#undef INCLUDE_ALLOW_USERLEVEL
+
+#if defined MODULE && !defined VMKERNEL_MODULE && \
+    !defined VMMON && !defined INCLUDE_ALLOW_MODULE
+#error "The surrounding include file is not allowed in driver modules."
+#endif
+#undef INCLUDE_ALLOW_MODULE
+
+#if defined VMMON && !defined INCLUDE_ALLOW_VMMON
+#error "The surrounding include file is not allowed in vmmon."
+#endif
+#undef INCLUDE_ALLOW_VMMON
+
+#if defined VMKERNEL && !defined INCLUDE_ALLOW_VMKERNEL
+#error "The surrounding include file is not allowed in the vmkernel."
+#endif
+#undef INCLUDE_ALLOW_VMKERNEL
+
+#if defined GPLED_CODE && !defined INCLUDE_ALLOW_DISTRIBUTE
+#error "The surrounding include file is not allowed in GPL code."
+#endif
+#undef INCLUDE_ALLOW_DISTRIBUTE
+
+#if defined VMKERNEL_MODULE && !defined VMKERNEL && \
+    !defined INCLUDE_ALLOW_VMK_MODULE && !defined INCLUDE_ALLOW_VMKDRIVERS
+#error "The surrounding include file is not allowed in vmkernel modules."
+#endif
+#undef INCLUDE_ALLOW_VMK_MODULE
+#undef INCLUDE_ALLOW_VMKDRIVERS
+
+#if defined VMIROM && ! defined INCLUDE_ALLOW_VMIROM
+#error "The surrounding include file is not allowed in vmirom."
+#endif
+#undef INCLUDE_ALLOW_VMIROM
diff --git a/sys/dev/virtual/vmware/shared/vm_assert.h b/sys/dev/virtual/vmware/shared/vm_assert.h
new file mode 100644
index 0000000..6b88c7a
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_assert.h
@@ -0,0 +1,354 @@
+/*********************************************************
+ * Copyright (C) 1998-2004 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * vm_assert.h --
+ *
+ *	The basic assertion facility for all VMware code.
+ *
+ *	For proper use, see
+ *	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
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+// XXX not necessary except some places include vm_assert.h improperly
+#include "vm_basic_types.h"
+#include "vm_basic_defs.h"
+
+
+/*
+ * XXX old file code
+ */
+
+#ifdef FILECODEINT
+#error "Don't define FILECODEINT.  It is obsolete."
+#endif
+#ifdef FILECODE
+#error "Don't define FILECODE.  It is obsolete."
+#endif
+
+
+/*
+ * Panic and log functions
+ */
+
+EXTERN void Log(const char *fmt, ...) PRINTF_DECL(1, 2);
+EXTERN void Warning(const char *fmt, ...) PRINTF_DECL(1, 2);
+EXTERN NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
+
+EXTERN void LogThrottled(uint32 *count, const char *fmt, ...)
+            PRINTF_DECL(2, 3);
+EXTERN void WarningThrottled(uint32 *count, const char *fmt, ...)
+            PRINTF_DECL(2, 3);
+
+/* DB family:  messages which are parsed by logfile database system */
+#define WarningDB Warning
+#define LogDB Log
+#define WarningThrottledDB WarningThrottled
+#define LogThrottledDB LogThrottled
+
+
+/*
+ * Stress testing: redefine ASSERT_IFNOT() to taste
+ */
+
+#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 || defined ASSERT_ALWAYS_AVAILABLE
+#undef ASSERT
+#define ASSERT(cond) \
+           ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertAssert))
+#endif
+#define ASSERT_BUG(bug, cond) \
+           ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG(bug, AssertAssert))
+#define ASSERT_BUG_DEBUGONLY(bug, cond) ASSERT_BUG(bug, cond)
+
+#define PANIC()        _ASSERT_PANIC(AssertPanic)
+#define PANIC_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertPanic)
+
+#define ASSERT_NOT_IMPLEMENTED(cond) \
+           ASSERT_IFNOT(cond, NOT_IMPLEMENTED())
+#define ASSERT_NOT_IMPLEMENTED_BUG(bug, cond) \
+           ASSERT_IFNOT(cond, NOT_IMPLEMENTED_BUG(bug))
+
+#define NOT_IMPLEMENTED()        _ASSERT_PANIC(AssertNotImplemented)
+#define NOT_IMPLEMENTED_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertNotImplemented)
+
+#define NOT_REACHED()            _ASSERT_PANIC(AssertNotReached)
+#define NOT_REACHED_BUG(bug)     _ASSERT_PANIC_BUG(bug, AssertNotReached)
+
+#define ASSERT_MEM_ALLOC(cond) \
+           ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertMemAlloc))
+
+#ifdef VMX86_DEVEL
+   #define ASSERT_LENGTH(real, expected) \
+              ASSERT_IFNOT((real) == (expected), \
+                 Panic(AssertLengthFmt, __FILE__, __LINE__, real, expected))
+#else
+   #define ASSERT_LENGTH(real, expected) ASSERT((real) == (expected))
+#endif
+
+#ifdef VMX86_DEVEL
+   #define ASSERT_DEVEL(cond) ASSERT(cond)
+#else
+   #define ASSERT_DEVEL(cond) ((void) 0)
+#endif
+
+#define ASSERT_NO_INTERRUPTS()  ASSERT(!INTERRUPTS_ENABLED())
+#define ASSERT_HAS_INTERRUPTS() ASSERT(INTERRUPTS_ENABLED())
+
+#define ASSERT_LOG_UNEXPECTED(bug, cond) \
+           (UNLIKELY(!(cond)) ? LOG_UNEXPECTED(bug) : 0)
+#ifdef VMX86_DEVEL
+   #define LOG_UNEXPECTED(bug) \
+              Warning(AssertUnexpectedFmt, __FILE__, __LINE__, bug)
+#else
+   #define LOG_UNEXPECTED(bug) \
+              Log(AssertUnexpectedFmt, __FILE__, __LINE__, bug)
+#endif
+
+#define ASSERT_NOT_TESTED(cond) (UNLIKELY(!(cond)) ? NOT_TESTED() : 0)
+#ifdef VMX86_DEVEL
+   #define NOT_TESTED() Warning(AssertNotTestedFmt, __FILE__, __LINE__)
+#else
+   #define NOT_TESTED() Log(AssertNotTestedFmt, __FILE__, __LINE__)
+#endif
+
+#define NOT_TESTED_ONCE()                                               \
+   do {                                                                 \
+      static Bool alreadyPrinted = FALSE;                               \
+      if (UNLIKELY(!alreadyPrinted)) {                                  \
+	 alreadyPrinted = TRUE;                                         \
+	 NOT_TESTED();                                                  \
+      }                                                                 \
+   } while (0)
+
+#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 {                                                                 \
+      static Bool logged = FALSE;                                       \
+      if (!logged) {                                                    \
+	 Log _s;                                                        \
+         logged = TRUE;                                                 \
+      }                                                                 \
+   } while (0)
+
+
+/*
+ * Redefine macros that are only in debug versions
+ */
+
+#if !defined VMX86_DEBUG && !defined ASSERT_ALWAYS_AVAILABLE // {
+
+#undef  ASSERT
+#define ASSERT(cond) ((void) 0)
+
+#undef  ASSERT_BUG_DEBUGONLY
+#define ASSERT_BUG_DEBUGONLY(bug, cond) ((void) 0)
+
+#undef  ASSERT_LENGTH
+#define ASSERT_LENGTH(real, expected) ((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.
+ */
+
+#ifdef VMM
+#undef  NOT_REACHED
+#define NOT_REACHED() ((void) 0)
+#else
+// keep debug definition
+#endif
+
+#undef  ASSERT_LOG_UNEXPECTED
+#define ASSERT_LOG_UNEXPECTED(bug, cond) ((void) 0)
+
+#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).
+ */
+
+#define ASSERT_ON_COMPILE(e) \
+   do { \
+      enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
+      typedef char AssertOnCompileFailed[AssertOnCompileMisused]; \
+   } while (0)
+
+
+/*
+ * 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 \
+   }
+
+
+/*
+ * 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 VMKERNEL
+// vmkernel Panic() function does not want a trailing newline.
+#define _ASSERT_PANIC(name) \
+           Panic(_##name##Fmt, __FILE__, __LINE__)
+#define _ASSERT_PANIC_BUG(bug, name) \
+           Panic(_##name##Fmt " bugNr=%d", __FILE__, __LINE__, bug)
+
+#else /* !VMKERNEL */
+#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)
+#endif /* VMKERNEL */
+
+#define AssertLengthFmt     _AssertLengthFmt
+#define AssertUnexpectedFmt _AssertUnexpectedFmt
+#define AssertNotTestedFmt  _AssertNotTestedFmt
+
+#endif // }
+
+// these don't have newline so a bug can be tacked on
+#define _AssertPanicFmt            "PANIC %s:%d"
+#define _AssertAssertFmt           "ASSERT %s:%d"
+#define _AssertNotImplementedFmt   "NOT_IMPLEMENTED %s:%d"
+#define _AssertNotReachedFmt       "NOT_REACHED %s:%d"
+#define _AssertMemAllocFmt         "MEM_ALLOC %s:%d"
+
+// these are complete formats with newline
+#define _AssertLengthFmt           "LENGTH %s:%d r=%#x e=%#x\n"
+#define _AssertUnexpectedFmt       "UNEXPECTED %s:%d bugNr=%d\n"
+#define _AssertNotTestedFmt        "NOT_TESTED %s:%d\n"
+
+#endif /* ifndef _VM_ASSERT_H_ */
diff --git a/sys/dev/virtual/vmware/shared/vm_atomic.h b/sys/dev/virtual/vmware/shared/vm_atomic.h
new file mode 100644
index 0000000..7cdddc9
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_atomic.h
@@ -0,0 +1,2448 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * vm_atomic.h --
+ *
+ *	Atomic power
+ *
+ * Note: Only partially tested on ARM processors: Works for View Open
+ *       Client, which shouldn't have threads.
+ *
+ *       In ARM, GCC intrinsics (__sync*) compile but might not
+ *       work, while MS intrinsics (_Interlocked*) do not compile,
+ *       and ARM has no equivalent to the "lock" instruction prior to
+ *       ARMv6; the current ARM target is ARMv5.  According to glibc
+ *       documentation, ARMv5 cannot have atomic code in user space.
+ *       Instead a Linux system call to kernel code referenced in
+ *       entry-armv.S is used to achieve atomic functions.  See bug
+ *       478054 for details.
+ */
+
+#ifndef _ATOMIC_H_
+#define _ATOMIC_H_
+
+//#define FAKE_ATOMIC /* defined if true atomic not needed */
+
+#define INCLUDE_ALLOW_USERLEVEL
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMKDRIVERS
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_DISTRIBUTE
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+
+/* Basic atomic type: 32 bits */
+typedef struct Atomic_uint32 {
+   volatile uint32 value;
+} Atomic_uint32;
+
+
+/* Basic atomic type: 64 bits */
+typedef struct  Atomic_uint64 {
+   volatile uint64 value;
+} Atomic_uint64 ALIGNED(8);
+
+
+/*
+ * Prototypes for msft atomics.  These are defined & inlined by the
+ * compiler so no function definition is needed.  The prototypes are
+ * needed for c++.  Since amd64 compiler doesn't support inline asm we
+ * have to use these.  Unfortunately, we still have to use some inline asm
+ * for the 32 bit code since the and/or/xor implementations didn't show up
+ * untill xp or 2k3.
+ *
+ * The declarations for the intrinsic functions were taken from ntddk.h
+ * in the DDK. The declarations must match 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) && _MSC_VER >= 1310
+#ifdef __cplusplus
+extern "C" {
+#endif
+long  _InterlockedExchange(long volatile*, long);
+long  _InterlockedCompareExchange(long volatile*, long, long);
+long  _InterlockedExchangeAdd(long volatile*, long);
+long  _InterlockedDecrement(long volatile*);
+long  _InterlockedIncrement(long volatile*);
+#pragma intrinsic(_InterlockedExchange, _InterlockedCompareExchange)
+#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedDecrement)
+#pragma intrinsic(_InterlockedIncrement)
+
+#if defined(VM_X86_64)
+long     _InterlockedAnd(long volatile*, long);
+__int64  _InterlockedAnd64(__int64 volatile*, __int64);
+long     _InterlockedOr(long volatile*, long);
+__int64  _InterlockedOr64(__int64 volatile*, __int64);
+long     _InterlockedXor(long volatile*, long);
+__int64  _InterlockedXor64(__int64 volatile*, __int64);
+__int64  _InterlockedExchangeAdd64(__int64 volatile*, __int64);
+__int64  _InterlockedIncrement64(__int64 volatile*);
+__int64  _InterlockedDecrement64(__int64 volatile*);
+__int64  _InterlockedExchange64(__int64 volatile*, __int64);
+__int64  _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
+#if !defined(_WIN64)
+#pragma intrinsic(_InterlockedAnd, _InterlockedAnd64)
+#pragma intrinsic(_InterlockedOr, _InterlockedOr64)
+#pragma intrinsic(_InterlockedXor, _InterlockedXor64)
+#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedIncrement64)
+#pragma intrinsic(_InterlockedDecrement64, _InterlockedExchange64)
+#pragma intrinsic(_InterlockedCompareExchange64)
+#endif /* !_WIN64 */
+#endif /* __x86_64__ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MSC_VER */
+
+#ifdef __arm__
+#   if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||  \
+       defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__)
+#      define VM_ARM_V7
+#   else
+#     error Only ARMv7 extends the synchronization primitives ldrex/strex.   \
+            For the lower ARM version, please implement the atomic functions \
+            by kernel APIs.
+#   endif
+#endif
+
+/* Data Memory Barrier */
+#ifdef VM_ARM_V7
+#define dmb() __asm__ __volatile__("dmb" : : : "memory")
+#endif
+
+
+/* Convert a volatile uint32 to Atomic_uint32. */
+static INLINE Atomic_uint32 *
+Atomic_VolatileToAtomic(volatile uint32 *var)
+{
+   return (Atomic_uint32 *)var;
+}
+
+/* Convert a volatile uint64 to Atomic_uint64. */
+static INLINE Atomic_uint64 *
+Atomic_VolatileToAtomic64(volatile uint64 *var)
+{
+   return (Atomic_uint64 *)var;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Init, Atomic_SetFence, AtomicUseFence --
+ *
+ *      Determine whether an lfence intruction is executed after
+ *	every locked instruction.
+ *
+ *	Certain AMD processes have a bug (see bug 107024) that
+ *	requires an lfence after every locked instruction.
+ *
+ *	The global variable AtomicUseFence controls whether lfence
+ *	is used (see AtomicEpilogue).
+ *
+ *	Atomic_SetFence sets AtomicUseFence to the given value.
+ *
+ *	Atomic_Init computes and sets AtomicUseFence for x86.
+ *	It does not take into account the number of processors.
+ *
+ *	The rationale for all this complexity is that Atomic_Init
+ *	is the easy-to-use interface.  It can be called a number
+ *	of times cheaply, and does not depend on other libraries.
+ *	However, because the number of CPUs is difficult to compute,
+ *	it does without it and always assumes there are more than one.
+ *
+ *	For programs that care or have special requirements,
+ *	Atomic_SetFence can be called directly, in addition to Atomic_Init.
+ *	It overrides the effect of Atomic_Init, and can be called
+ *	before, after, or between calls to Atomic_Init.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+// The freebsd assembler doesn't know the lfence instruction
+#if defined(__GNUC__) &&                                                \
+     __GNUC__ >= 3 &&                                                   \
+    (defined(__VMKERNEL__) || !defined(__DragonFly__)) &&               \
+    (!defined(MODULE) || defined(__VMKERNEL_MODULE__)) &&               \
+    !defined(__APPLE__) &&                                              \
+    (defined(__i386__) || defined(__x86_64__)) /* PR136775 */
+#define ATOMIC_USE_FENCE
+#endif
+
+#if defined(VMATOMIC_IMPORT_DLLDATA)
+VMX86_EXTERN_DATA Bool AtomicUseFence;
+#else
+EXTERN Bool AtomicUseFence;
+#endif
+
+EXTERN Bool atomicFenceInitialized;
+
+void AtomicInitFence(void);
+
+static INLINE void
+Atomic_Init(void)
+{
+#ifdef ATOMIC_USE_FENCE
+   if (!atomicFenceInitialized) {
+      AtomicInitFence();
+   }
+#endif
+}
+
+static INLINE void
+Atomic_SetFence(Bool fenceAfterLock) /* IN: TRUE to enable lfence */
+                                     /*     FALSE to disable. */
+{
+   AtomicUseFence = fenceAfterLock;
+#if defined(__VMKERNEL__)
+   extern void Atomic_SetFenceVMKAPI(Bool fenceAfterLock);
+   Atomic_SetFenceVMKAPI(fenceAfterLock);
+#endif
+   atomicFenceInitialized = TRUE;
+}
+
+
+/* Conditionally execute fence after interlocked instruction. */
+static INLINE void
+AtomicEpilogue(void)
+{
+#ifdef ATOMIC_USE_FENCE
+#ifdef VMM
+      /* The monitor conditionally patches out the lfence when not needed.*/
+      /* Construct a MonitorPatchTextEntry in the .patchtext section. */
+   asm volatile ("1:\n\t"
+                 "lfence\n\t"
+                 "2:\n\t"
+                 ".pushsection .patchtext\n\t"
+                 ".quad 1b\n\t"
+                 ".quad 2b\n\t"
+                 ".popsection\n\t" ::: "memory");
+#else
+   if (UNLIKELY(AtomicUseFence)) {
+      asm volatile ("lfence" ::: "memory");
+   }
+#endif
+#endif
+}
+
+
+/*
+ * All the assembly code is tricky and written conservatively.
+ * For example, to make sure gcc won't introduce copies,
+ * we force the addressing mode like this:
+ *
+ *    "xchgl %0, (%1)"
+ *    : "=r" (val)
+ *    : "r" (&var->value),
+ *      "0" (val)
+ *    : "memory"
+ *
+ * - edward
+ *
+ * Actually - turns out that gcc never generates memory aliases (it
+ * still does generate register aliases though), so we can be a bit
+ * more agressive with the memory constraints. The code above can be
+ * modified like this:
+ *
+ *    "xchgl %0, %1"
+ *    : "=r" (val),
+ *      "=m" (var->value),
+ *    : "0" (val),
+ *      "1" (var->value)
+ *
+ * The advantages are that gcc can use whatever addressing mode it
+ * likes to access the memory value, and that we dont have to use a
+ * way-too-generic "memory" clobber as there is now an explicit
+ * declaration that var->value is modified.
+ *
+ * see also /usr/include/asm/atomic.h to convince yourself this is a
+ * valid optimization.
+ *
+ * - walken
+ */
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Read --
+ *
+ *      Read
+ *
+ * Results:
+ *      The value of the atomic variable.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_Read(Atomic_uint32 const *var) // IN
+{
+   return var->value;
+}
+#define Atomic_Read32 Atomic_Read
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Write --
+ *
+ *      Write
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Write(Atomic_uint32 *var, // IN
+             uint32 val)         // IN
+{
+   var->value = val;
+}
+#define Atomic_Write32 Atomic_Write
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadWrite --
+ *
+ *      Read followed by write
+ *
+ * Results:
+ *      The value of the atomic variable before the write.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_ReadWrite(Atomic_uint32 *var, // IN
+                 uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 retVal;
+   register volatile uint32 res;
+
+   dmb();
+
+   __asm__ __volatile__(
+   "1: ldrex %[retVal], [%[var]] \n\t"
+      "strex %[res], %[val], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [retVal] "=&r" (retVal), [res] "=&r" (res)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+
+   return retVal;
+#else // __VM_ARM_V7 (assume x86*)
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "xchgl %0, %1"
+      : "=r" (val),
+	"+m" (var->value)
+      : "0" (val)
+   );
+   AtomicEpilogue();
+   return val;
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   return _InterlockedExchange((long *)&var->value, (long)val);
+#else
+#pragma warning(push)
+#pragma warning(disable : 4035)         // disable no-return warning
+   {
+      __asm mov eax, val
+      __asm mov ebx, var
+      __asm xchg [ebx]Atomic_uint32.value, eax
+      // eax is the return value, this is documented to work - edward
+   }
+#pragma warning(pop)
+#endif // _MSC_VER >= 1310
+#else
+#error No compiler defined for Atomic_ReadWrite
+#endif // __GNUC__
+}
+#define Atomic_ReadWrite32 Atomic_ReadWrite
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadIfEqualWrite --
+ *
+ *      Compare exchange: Read variable, if equal to oldVal, write newVal
+ *
+ * Results:
+ *      The value of the atomic variable before the write.
+ *
+ * Side effects:
+ *      The variable may be modified.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
+                        uint32 oldVal,      // IN
+                        uint32 newVal)      // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register uint32 retVal;
+   register uint32 res;
+
+   dmb();
+
+   __asm__ __volatile__(
+   "1: ldrex %[retVal], [%[var]] \n\t"
+      "mov %[res], #1 \n\t"
+      "teq %[retVal], %[oldVal] \n\t"
+      "strexeq %[res], %[newVal], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [retVal] "=&r" (retVal), [res] "=&r" (res)
+      : [var] "r" (&var->value), [oldVal] "r" (oldVal), [newVal] "r" (newVal)
+      : "memory", "cc"
+   );
+
+   dmb();
+
+   return retVal;
+#else // VM_ARM_V7 (assume x86*)
+   uint32 val;
+
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; cmpxchgl %2, %1"
+      : "=a" (val),
+	"+m" (var->value)
+      : "r" (newVal),
+	"0" (oldVal)
+      : "cc"
+   );
+   AtomicEpilogue();
+   return val;
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   return _InterlockedCompareExchange((long *)&var->value,
+				      (long)newVal,
+				      (long)oldVal);
+#else
+#pragma warning(push)
+#pragma warning(disable : 4035)         // disable no-return warning
+   {
+      __asm mov eax, oldVal
+      __asm mov ebx, var
+      __asm mov ecx, newVal
+      __asm lock cmpxchg [ebx]Atomic_uint32.value, ecx
+      // eax is the return value, this is documented to work - edward
+   }
+#pragma warning(pop)
+#endif
+#else
+#error No compiler defined for Atomic_ReadIfEqualWrite
+#endif
+}
+#define Atomic_ReadIfEqualWrite32 Atomic_ReadIfEqualWrite
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadIfEqualWrite64 --
+ *
+ *      Compare exchange: Read variable, if equal to oldVal, write newVal
+ *
+ * Results:
+ *      The value of the atomic variable before the write.
+ *
+ * Side effects:
+ *      The variable may be modified.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadIfEqualWrite64(Atomic_uint64 *var, // IN
+                          uint64 oldVal,      // IN
+                          uint64 newVal)      // IN
+{
+#if defined(__GNUC__)
+   uint64 val;
+
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; cmpxchgq %2, %1"
+      : "=a" (val),
+	"+m" (var->value)
+      : "r" (newVal),
+	"0" (oldVal)
+      : "cc"
+   );
+   AtomicEpilogue();
+   return val;
+#elif defined _MSC_VER
+   return _InterlockedCompareExchange64((__int64 *)&var->value,
+					(__int64)newVal,
+					(__int64)oldVal);
+#else
+#error No compiler defined for Atomic_ReadIfEqualWrite64
+#endif
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_And --
+ *
+ *      Atomic read, bitwise AND with a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_And(Atomic_uint32 *var, // IN
+           uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 res;
+   register volatile uint32 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+   "1: ldrex %[tmp], [%[var]] \n\t"
+      "and %[tmp], %[val] \n\t"
+      "strex %[res], %[tmp], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [res] "=&r" (res), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+#else /* VM_ARM_V7 */
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; andl %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if defined(__x86_64__)
+   _InterlockedAnd((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock and [ebx]Atomic_uint32.value, eax
+#endif
+#else
+#error No compiler defined for Atomic_And
+#endif
+}
+#define Atomic_And32 Atomic_And
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Or --
+ *
+ *      Atomic read, bitwise OR with a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Or(Atomic_uint32 *var, // IN
+          uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 res;
+   register volatile uint32 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+   "1: ldrex %[tmp], [%[var]] \n\t"
+      "orr %[tmp], %[val] \n\t"
+      "strex %[res], %[tmp], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [res] "=&r" (res), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; orl %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if defined(__x86_64__)
+   _InterlockedOr((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock or [ebx]Atomic_uint32.value, eax
+#endif
+#else
+#error No compiler defined for Atomic_Or
+#endif
+}
+#define Atomic_Or32 Atomic_Or
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Xor --
+ *
+ *      Atomic read, bitwise XOR with a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Xor(Atomic_uint32 *var, // IN
+           uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 res;
+   register volatile uint32 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+   "1: ldrex %[tmp], [%[var]] \n\t"
+      "eor %[tmp], %[val] \n\t"
+      "strex %[res], %[tmp], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [res] "=&r" (res), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; xorl %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if defined(__x86_64__)
+   _InterlockedXor((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock xor [ebx]Atomic_uint32.value, eax
+#endif
+#else
+#error No compiler defined for Atomic_Xor
+#endif
+}
+#define Atomic_Xor32 Atomic_Xor
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Xor64 --
+ *
+ *      Atomic read, bitwise XOR with a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Xor64(Atomic_uint64 *var, // IN
+             uint64 val)         // IN
+{
+#if defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; xorq %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedXor64((__int64 *)&var->value, (__int64)val);
+#else
+#error No compiler defined for Atomic_Xor64
+#endif
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Add --
+ *
+ *      Atomic read, add a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Add(Atomic_uint32 *var, // IN
+           uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 res;
+   register volatile uint32 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+   "1: ldrex %[tmp], [%[var]] \n\t"
+      "add %[tmp], %[val] \n\t"
+      "strex %[res], %[tmp], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [res] "=&r" (res), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; addl %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   _InterlockedExchangeAdd((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock add [ebx]Atomic_uint32.value, eax
+#endif
+#else
+#error No compiler defined for Atomic_Add
+#endif
+}
+#define Atomic_Add32 Atomic_Add
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Add64 --
+ *
+ *      Atomic read, add a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Add64(Atomic_uint64 *var, // IN
+             uint64 val)         // IN
+{
+#if defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; addq %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedExchangeAdd64((__int64 *)&var->value, (__int64)val);
+#else
+#error No compiler defined for Atomic_Add64
+#endif
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Sub --
+ *
+ *      Atomic read, subtract a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Sub(Atomic_uint32 *var, // IN
+           uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 res;
+   register volatile uint32 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+      "1: ldrex %[tmp], [%[var]] \n\t"
+      "sub %[tmp], %[val] \n\t"
+      "strex %[res], %[tmp], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [res] "=&r" (res), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; subl %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   _InterlockedExchangeAdd((long *)&var->value, (long)-val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock sub [ebx]Atomic_uint32.value, eax
+#endif
+#else
+#error No compiler defined for Atomic_Sub
+#endif
+}
+#define Atomic_Sub32 Atomic_Sub
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Sub64 --
+ *
+ *      Atomic read, subtract a value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Sub64(Atomic_uint64 *var, // IN
+             uint64 val)         // IN
+{
+#ifdef __GNUC__
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; subq %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedExchangeAdd64((__int64 *)&var->value, (__int64)-val);
+#else
+#error No compiler defined for Atomic_Sub64
+#endif
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Inc --
+ *
+ *      Atomic read, increment, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Inc(Atomic_uint32 *var) // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   Atomic_Add(var, 1);
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; incl %0"
+      : "+m" (var->value)
+      :
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   _InterlockedIncrement((long *)&var->value);
+#else
+   __asm mov ebx, var
+   __asm lock inc [ebx]Atomic_uint32.value
+#endif
+#else
+#error No compiler defined for Atomic_Inc
+#endif
+}
+#define Atomic_Inc32 Atomic_Inc
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Dec --
+ *
+ *      Atomic read, decrement, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Dec(Atomic_uint32 *var) // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   Atomic_Sub(var, 1);
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; decl %0"
+      : "+m" (var->value)
+      :
+      : "cc"
+   );
+   AtomicEpilogue();
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   _InterlockedDecrement((long *)&var->value);
+#else
+   __asm mov ebx, var
+   __asm lock dec [ebx]Atomic_uint32.value
+#endif
+#else
+#error No compiler defined for Atomic_Dec
+#endif
+}
+#define Atomic_Dec32 Atomic_Dec
+
+
+/*
+ * Note that the technique below can be used to implement ReadX(), where X is
+ * an arbitrary mathematical function.
+ */
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_FetchAndOr --
+ *
+ *      Atomic read (returned), bitwise OR with a value, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_FetchAndOr(Atomic_uint32 *var, // IN
+                  uint32 val)         // IN
+{
+   uint32 res;
+
+   do {
+      res = Atomic_Read(var);
+   } while (res != Atomic_ReadIfEqualWrite(var, res, res | val));
+
+   return res;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_FetchAndAnd --
+ *
+ *      Atomic read (returned), bitwise And with a value, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_FetchAndAnd(Atomic_uint32 *var, // IN
+                   uint32 val)         // IN
+{
+   uint32 res;
+
+   do {
+      res = Atomic_Read(var);
+   } while (res != Atomic_ReadIfEqualWrite(var, res, res & val));
+
+   return res;
+}
+#define Atomic_ReadOr32 Atomic_FetchAndOr
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadOr64 --
+ *
+ *      Atomic read (returned), bitwise OR with a value, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadOr64(Atomic_uint64 *var, // IN
+                uint64 val)         // IN
+{
+   uint64 res;
+
+   do {
+      res = var->value;
+   } while (res != Atomic_ReadIfEqualWrite64(var, res, res | val));
+
+   return res;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadAnd64 --
+ *
+ *      Atomic read (returned), bitwise AND with a value, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadAnd64(Atomic_uint64 *var, // IN
+                 uint64 val)         // IN
+{
+   uint64 res;
+
+   do {
+      res = var->value;
+   } while (res != Atomic_ReadIfEqualWrite64(var, res, res & val));
+
+   return res;
+}
+#endif // __x86_64__
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_FetchAndAddUnfenced --
+ *
+ *      Atomic read (returned), add a value, write.
+ *
+ *      If you have to implement FetchAndAdd() on an architecture other than
+ *      x86 or x86-64, you might want to consider doing something similar to
+ *      Atomic_FetchAndOr().
+ *
+ *      The "Unfenced" version of Atomic_FetchAndInc never executes
+ *      "lfence" after the interlocked operation.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_FetchAndAddUnfenced(Atomic_uint32 *var, // IN
+                           uint32 val)         // IN
+{
+#ifdef __GNUC__
+#ifdef VM_ARM_V7
+   register volatile uint32 res;
+   register volatile uint32 retVal;
+
+   dmb();
+
+   __asm__ __volatile__(
+      "1: ldrex %[retVal], [%[var]] \n\t"
+      "add %[val], %[retVal] \n\t"
+      "strex %[res], %[val], [%[var]] \n\t"
+      "teq %[res], #0 \n\t"
+      "bne 1b"
+      : [res] "=&r" (res), [retVal] "=&r" (retVal)
+      : [var] "r" (&var->value), [val] "r" (val)
+      : "memory", "cc"
+   );
+
+   dmb();
+
+   return retVal;
+#else // VM_ARM_V7
+   /* Checked against the Intel manual and GCC --walken */
+   __asm__ __volatile__(
+      "lock; xaddl %0, %1"
+      : "=r" (val),
+	"+m" (var->value)
+      : "0" (val)
+      : "cc"
+   );
+   return val;
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if _MSC_VER >= 1310
+   return _InterlockedExchangeAdd((long *)&var->value, (long)val);
+#else
+#pragma warning(push)
+#pragma warning(disable : 4035)         // disable no-return warning
+   {
+      __asm mov eax, val
+      __asm mov ebx, var
+      __asm lock xadd [ebx]Atomic_uint32.value, eax
+   }
+#pragma warning(pop)
+#endif
+#else
+#error No compiler defined for Atomic_FetchAndAdd
+#endif
+}
+#define Atomic_ReadAdd32 Atomic_FetchAndAdd
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_FetchAndAdd --
+ *
+ *      Atomic read (returned), add a value, write.
+ *
+ *      If you have to implement FetchAndAdd() on an architecture other than
+ *      x86 or x86-64, you might want to consider doing something similar to
+ *      Atomic_FetchAndOr().
+ *
+ *      Unlike "Unfenced" version, this one may execute the "lfence" after
+ *      interlocked operation.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_FetchAndAdd(Atomic_uint32 *var, // IN
+                   uint32 val)         // IN
+{
+#if defined(__GNUC__) && !defined(VM_ARM_V7)
+   val = Atomic_FetchAndAddUnfenced(var, val);
+   AtomicEpilogue();
+   return val;
+#else
+   return Atomic_FetchAndAddUnfenced(var, val);
+#endif
+}
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadAdd64 --
+ *
+ *      Atomic read (returned), add a value, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadAdd64(Atomic_uint64 *var, // IN
+                 uint64 val)         // IN
+{
+#if defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; xaddq %0, %1"
+      : "=r" (val),
+	"+m" (var->value)
+      : "0" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+   return val;
+#elif defined _MSC_VER
+   return _InterlockedExchangeAdd64((__int64 *)&var->value, (__int64)val);
+#else
+#error No compiler defined for Atomic_ReadAdd64
+#endif
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_FetchAndInc --
+ *
+ *      Atomic read (returned), increment, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_FetchAndInc(Atomic_uint32 *var) // IN
+{
+   return Atomic_FetchAndAdd(var, 1);
+}
+#define Atomic_ReadInc32 Atomic_FetchAndInc
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadInc64 --
+ *
+ *      Atomic read (returned), increment, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadInc64(Atomic_uint64 *var) // IN
+{
+   return Atomic_ReadAdd64(var, 1);
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_FetchAndDec --
+ *
+ *      Atomic read (returned), decrement, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Atomic_FetchAndDec(Atomic_uint32 *var) // IN
+{
+   return Atomic_FetchAndAdd(var, (uint32)-1);
+}
+#define Atomic_ReadDec32 Atomic_FetchAndDec
+
+
+#if defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadDec64 --
+ *
+ *      Atomic read (returned), decrement, write.
+ *
+ * Results:
+ *      The value of the variable before the operation.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadDec64(Atomic_uint64 *var) // IN
+{
+   return Atomic_ReadAdd64(var, CONST64U(-1));
+}
+#endif
+
+
+#ifdef VMKERNEL
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CMPXCHG1B --
+ *
+ *      Compare and exchange a single byte.
+ *
+ * Results:
+ *      The value read from ptr.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+static INLINE uint8
+CMPXCHG1B(volatile uint8 *ptr, // IN
+          uint8 oldVal,        // IN
+          uint8 newVal)        // IN
+{
+   uint8 val;
+   __asm__ __volatile__("lock; cmpxchgb %b2, %1"
+                        : "=a" (val),
+                          "+m" (*ptr)
+                        : "r" (newVal),
+                          "0" (oldVal)
+                        : "cc");
+   return val;
+}
+#endif
+
+
+/*
+ * Usage of this helper struct is strictly reserved to the following
+ * function. --hpreg
+ */
+typedef struct {
+   uint32 lowValue;
+   uint32 highValue;
+} S_uint64;
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_CMPXCHG64 --
+ *
+ *      Compare exchange: Read variable, if equal to oldVal, write newVal
+ *
+ *      XXX: Ensure that if this function is to be inlined by gcc, it is
+ *      compiled with -fno-strict-aliasing. Otherwise it will break.
+ *      Unfortunately we know that gcc 2.95.3 (used to build the FreeBSD 3.2
+ *      Tools) does not honor -fno-strict-aliasing. As a workaround, we avoid
+ *      inlining the function entirely for versions of gcc under 3.0.
+ *
+ * Results:
+ *      TRUE if equal, FALSE if not equal
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__) && __GNUC__ < 3
+static Bool
+#else
+static INLINE Bool
+#endif
+Atomic_CMPXCHG64(Atomic_uint64 *var,   // IN/OUT
+                 uint64 const *oldVal, // IN
+                 uint64 const *newVal) // IN
+{
+#ifdef __GNUC__
+   Bool equal;
+
+   /* Checked against the Intel manual and GCC --walken */
+#if defined(__x86_64__)
+   uint64 dummy;
+   __asm__ __volatile__(
+      "lock; cmpxchgq %3, %0" "\n\t"
+      "sete %1"
+      : "+m" (*var),
+	"=qm" (equal),
+	"=a" (dummy)
+      : "r" (*newVal),
+        "2" (*oldVal)
+      : "cc"
+   );
+#elif !defined(VM_ARM_V7) /* 32-bit version for non-ARM */
+   int dummy1, dummy2;
+#   if defined __PIC__
+   /*
+    * Rules for __asm__ statements in __PIC__ code
+    * --------------------------------------------
+    *
+    * The compiler uses %ebx for __PIC__ code, so an __asm__ statement cannot
+    * clobber %ebx. The __asm__ statement can temporarily modify %ebx, but _for
+    * each parameter that is used while %ebx is temporarily modified_:
+    *
+    * 1) The constraint cannot be "m", because the memory location the compiler
+    *    chooses could then be relative to %ebx.
+    *
+    * 2) The constraint cannot be a register class which contains %ebx (such as
+    *    "r" or "q"), because the register the compiler chooses could then be
+    *    %ebx. (This happens when compiling the Fusion UI with gcc 4.2.1, Apple
+    *    build 5577.)
+    *
+    * For that reason alone, the __asm__ statement should keep the regions
+    * where it temporarily modifies %ebx as small as possible.
+    */
+#      if __GNUC__ < 3 // Part of #188541 - for RHL 6.2 etc.
+   __asm__ __volatile__(
+      "xchg %%ebx, %6"       "\n\t"
+      "mov 4(%%ebx), %%ecx"  "\n\t"
+      "mov (%%ebx), %%ebx"   "\n\t"
+      "lock; cmpxchg8b (%3)" "\n\t"
+      "xchg %%ebx, %6"       "\n\t"
+      "sete %0"
+      : "=a" (equal),
+        "=d" (dummy2),
+        "=D" (dummy1)
+      : /*
+         * See the "Rules for __asm__ statements in __PIC__ code" above: %3
+         * must use a register class which does not contain %ebx.
+         */
+        "S" (var),
+        "0" (((S_uint64 const *)oldVal)->lowValue),
+        "1" (((S_uint64 const *)oldVal)->highValue),
+        "D" (newVal)
+      : "ecx", "cc", "memory"
+   );
+#      else
+   __asm__ __volatile__(
+      "xchgl %%ebx, %6"      "\n\t"
+      "lock; cmpxchg8b (%3)" "\n\t"
+      "xchgl %%ebx, %6"      "\n\t"
+      "sete %0"
+      :	"=qm,qm" (equal),
+	"=a,a" (dummy1),
+	"=d,d" (dummy2)
+      : /*
+         * See the "Rules for __asm__ statements in __PIC__ code" above: %3
+         * must use a register class which does not contain %ebx.
+         * "a"/"c"/"d" are already used, so we are left with either "S" or "D".
+         */
+        "S,D" (var),
+        "1,1" (((S_uint64 const *)oldVal)->lowValue),
+        "2,2" (((S_uint64 const *)oldVal)->highValue),
+        // %6 cannot use "m": 'newVal' is read-only.
+        "r,r" (((S_uint64 const *)newVal)->lowValue),
+        "c,c" (((S_uint64 const *)newVal)->highValue)
+      : "cc", "memory"
+   );
+#      endif
+#   else
+   __asm__ __volatile__(
+      "lock; cmpxchg8b %0" "\n\t"
+      "sete %1"
+      : "+m" (*var),
+	"=qm" (equal),
+	"=a" (dummy1),
+	"=d" (dummy2)
+      : "2" (((S_uint64 const *)oldVal)->lowValue),
+        "3" (((S_uint64 const *)oldVal)->highValue),
+        "b" (((S_uint64 const *)newVal)->lowValue),
+        "c" (((S_uint64 const *)newVal)->highValue)
+      : "cc"
+   );
+#   endif
+#elif defined(VM_ARM_V7)
+   volatile uint64 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+      "ldrexd %[tmp], %H[tmp], [%[var]] \n\t"
+      "mov %[equal], #1 \n\t"
+      "teq %[tmp], %[oldVal] \n\t"
+      "teqeq %H[tmp], %H[oldVal] \n\t"
+      "strexdeq  %[equal], %[newVal], %H[newVal], [%[var]]"
+      : [equal] "=&r" (equal), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [oldVal] "r" (*oldVal), [newVal] "r" (*newVal)
+      : "memory", "cc"
+   );
+
+   dmb();
+
+   return !equal;
+#endif
+#ifndef VM_ARM_V7
+   AtomicEpilogue();
+   return equal;
+#endif // VM_ARM_V7
+#elif defined _MSC_VER
+#if defined(__x86_64__)
+   return (__int64)*oldVal == _InterlockedCompareExchange64((__int64 *)&var->value,
+                                                            (__int64)*newVal,
+                                                            (__int64)*oldVal);
+#else
+#pragma warning(push)
+#pragma warning(disable : 4035)		// disable no-return warning
+   {
+      __asm mov esi, var
+      __asm mov edx, oldVal
+      __asm mov ecx, newVal
+      __asm mov eax, [edx]S_uint64.lowValue
+      __asm mov edx, [edx]S_uint64.highValue
+      __asm mov ebx, [ecx]S_uint64.lowValue
+      __asm mov ecx, [ecx]S_uint64.highValue
+      __asm lock cmpxchg8b [esi]
+      __asm sete al
+      __asm movzx eax, al
+      // eax is the return value, this is documented to work - edward
+   }
+#pragma warning(pop)
+#endif
+#else
+#error No compiler defined for Atomic_CMPXCHG64
+#endif // !GNUC
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_CMPXCHG32 --
+ *
+ *      Compare exchange: Read variable, if equal to oldVal, write newVal
+ *
+ * Results:
+ *      TRUE if equal, FALSE if not equal
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Atomic_CMPXCHG32(Atomic_uint32 *var,   // IN/OUT
+                 uint32 oldVal, // IN
+                 uint32 newVal) // IN
+{
+#ifdef __GNUC__
+   Bool equal;
+#ifdef VM_ARM_V7
+   volatile uint64 tmp;
+
+   dmb();
+
+   __asm__ __volatile__(
+      "ldrex %[tmp], [%[var]] \n\t"
+      "mov %[equal], #1 \n\t"
+      "teq %[tmp], %[oldVal] \n\t"
+      "strexeq  %[equal], %[newVal], [%[var]]"
+      : [equal] "=&r" (equal), [tmp] "=&r" (tmp)
+      : [var] "r" (&var->value), [oldVal] "r" (oldVal), [newVal] "r" (newVal)
+      : "memory", "cc"
+   );
+
+   dmb();
+
+   return !equal;
+#else // VM_ARM_V7
+   uint32 dummy;
+
+   __asm__ __volatile__(
+      "lock; cmpxchgl %3, %0" "\n\t"
+      "sete %1"
+      : "+m" (*var),
+	"=qm" (equal),
+	"=a" (dummy)
+      : "r" (newVal),
+        "2" (oldVal)
+      : "cc"
+   );
+   AtomicEpilogue();
+   return equal;
+#endif // VM_ARM_V7
+#else // defined(__GNUC__)
+   return (Atomic_ReadIfEqualWrite(var, oldVal, newVal) == oldVal);
+#endif // !defined(__GNUC__)
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Read64 --
+ *
+ *      Read and return.
+ *
+ * Results:
+ *      The value of the atomic variable.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_Read64(Atomic_uint64 const *var) // IN
+{
+#if defined(__GNUC__) && defined(__x86_64__)
+   uint64 value;
+
+#ifdef VMM
+   ASSERT((uintptr_t)var % 8 == 0);
+#endif
+   /*
+    * Use asm to ensure we emit a single load.
+    */
+   __asm__ __volatile__(
+      "movq %1, %0"
+      : "=r" (value)
+      : "m" (var->value)
+   );
+   return value;
+#elif defined(__GNUC__) && defined(__i386__)
+   uint64 value;
+   /*
+    * Since cmpxchg8b will replace the contents of EDX:EAX with the
+    * value in memory if there is no match, we need only execute the
+    * instruction once in order to atomically read 64 bits from
+    * memory.  The only constraint is that ECX:EBX must have the same
+    * value as EDX:EAX so that if the comparison succeeds.  We
+    * intentionally don't tell gcc that we are using ebx and ecx as we
+    * don't modify them and do not care what value they store.
+    */
+   __asm__ __volatile__(
+      "mov %%ebx, %%eax"   "\n\t"
+      "mov %%ecx, %%edx"   "\n\t"
+      "lock; cmpxchg8b %1"
+      : "=&A" (value)
+      : "m" (*var)
+      : "cc"
+   );
+   AtomicEpilogue();
+   return value;
+#elif defined (_MSC_VER) && defined(__x86_64__)
+   /*
+    * Microsoft docs guarantee "Simple reads and writes to properly
+    * aligned 64-bit variables are atomic on 64-bit Windows."
+    * http://msdn.microsoft.com/en-us/library/ms684122%28VS.85%29.aspx
+    *
+    * XXX Verify that value is properly aligned. Bug 61315.
+    */
+   return var->value;
+#elif defined (_MSC_VER) && defined(__i386__)
+#   pragma warning(push)
+#   pragma warning(disable : 4035)		// disable no-return warning
+   {
+      __asm mov ecx, var
+      __asm mov edx, ecx
+      __asm mov eax, ebx
+      __asm lock cmpxchg8b [ecx]
+      // edx:eax is the return value; this is documented to work. --mann
+   }
+#   pragma warning(pop)
+#elif defined(__GNUC__) && defined (VM_ARM_V7)
+   uint64 value;
+
+   __asm__ __volatile__(
+      "ldrexd %[value], %H[value], [%[var]] \n\t"
+      : [value] "=&r" (value)
+      : [var] "r" (&var->value)
+   );
+
+   return value;
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_ReadUnaligned64 --
+ *
+ *      Atomically read a 64 bit integer, possibly misaligned.
+ *      This function can be *very* expensive, costing over 50 kcycles
+ *      on Nehalem.
+ *
+ *      Note that "var" needs to be writable, even though it will not
+ *      be modified.
+ *
+ * Results:
+ *      The value of the atomic variable.
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+#if defined(__x86_64__)
+static INLINE uint64
+Atomic_ReadUnaligned64(Atomic_uint64 const *var)
+{
+   return Atomic_ReadIfEqualWrite64((Atomic_uint64*)var, 0, 0);
+}
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_FetchAndAdd64 --
+ *
+ *      Atomically adds a 64-bit integer to another
+ *
+ * Results:
+ *      Returns the old value just prior to the addition
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_FetchAndAdd64(Atomic_uint64 *var, // IN/OUT
+		     uint64 addend)      // IN
+{
+   uint64 oldVal;
+   uint64 newVal;
+
+   do {
+      oldVal = var->value;
+      newVal = oldVal + addend;
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &newVal));
+
+   return oldVal;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_FetchAndInc64 --
+ *
+ *      Atomically increments a 64-bit integer
+ *
+ * Results:
+ *      Returns the old value just prior to incrementing
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_FetchAndInc64(Atomic_uint64 *var) // IN/OUT
+{
+   return Atomic_FetchAndAdd64(var, 1);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_FetchAndDec64 --
+ *
+ *      Atomically decrements a 64-bit integer
+ *
+ * Results:
+ *      Returns the old value just prior to decrementing
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_FetchAndDec64(Atomic_uint64 *var) // IN/OUT
+{
+   uint64 oldVal;
+   uint64 newVal;
+
+   do {
+      oldVal = var->value;
+      newVal = oldVal - 1;
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &newVal));
+
+   return oldVal;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Inc64 --
+ *
+ *      Atomic read, increment, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Inc64(Atomic_uint64 *var) // IN
+{
+#if !defined(__x86_64__)
+   Atomic_FetchAndInc64(var);
+#elif defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; incq %0"
+      : "+m" (var->value)
+      :
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedIncrement64((__int64 *)&var->value);
+#else
+#error No compiler defined for Atomic_Inc64
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Dec64 --
+ *
+ *      Atomic read, decrement, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Dec64(Atomic_uint64 *var) // IN
+{
+#if !defined(__x86_64__)
+   Atomic_FetchAndDec64(var);
+#elif defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; decq %0"
+      : "+m" (var->value)
+      :
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedDecrement64((__int64 *)&var->value);
+#else
+#error No compiler defined for Atomic_Dec64
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_ReadWrite64 --
+ *
+ *      Read followed by write
+ *
+ * Results:
+ *      The value of the atomic variable before the write.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Atomic_ReadWrite64(Atomic_uint64 *var, // IN
+                   uint64 val)         // IN
+{
+#if defined(__x86_64__)
+#if defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "xchgq %0, %1"
+      : "=r" (val),
+	"+m" (var->value)
+      : "0" (val)
+   );
+   AtomicEpilogue();
+   return val;
+#elif defined _MSC_VER
+   return _InterlockedExchange64((__int64 *)&var->value, (__int64)val);
+#else
+#error No compiler defined for Atomic_ReadWrite64
+#endif
+#else
+   uint64 oldVal;
+
+   do {
+      oldVal = var->value;
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &val));
+
+   return oldVal;
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Write64 --
+ *
+ *      Write
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Write64(Atomic_uint64 *var, // IN
+               uint64 val)         // IN
+{
+#if defined(__x86_64__)
+#if defined(__GNUC__)
+
+#ifdef VMM
+   ASSERT((uintptr_t)var % 8 == 0);
+#endif
+   /*
+    * There is no move instruction for 64-bit immediate to memory, so unless
+    * the immediate value fits in 32-bit (i.e. can be sign-extended), GCC
+    * breaks the assignment into two movl instructions.  The code below forces
+    * GCC to load the immediate value into a register first.
+    */
+
+   __asm__ __volatile__(
+      "movq %1, %0"
+      : "=m" (var->value)
+      : "r" (val)
+   );
+#elif defined _MSC_VER
+   /*
+    * Microsoft docs guarantee "Simple reads and writes to properly aligned
+    * 64-bit variables are atomic on 64-bit Windows."
+    * http://msdn.microsoft.com/en-us/library/ms684122%28VS.85%29.aspx
+    *
+    * XXX Verify that value is properly aligned. Bug 61315.
+    */
+
+   var->value = val;
+#else
+#error No compiler defined for Atomic_Write64
+#endif
+#else  /* defined(__x86_64__) */
+   (void)Atomic_ReadWrite64(var, val);
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_Or64 --
+ *
+ *      Atomic read, bitwise OR with a 64-bit value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_Or64(Atomic_uint64 *var, // IN
+            uint64 val)         // IN
+{
+#if defined(__x86_64__)
+#if defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; orq %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedOr64((__int64 *)&var->value, (__int64)val);
+#else
+#error No compiler defined for Atomic_Or64
+#endif
+#else // __x86_64__
+   uint64 oldVal;
+   uint64 newVal;
+   do {
+      oldVal = var->value;
+      newVal = oldVal | val;
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &newVal));
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_And64 --
+ *
+ *      Atomic read, bitwise AND with a 64-bit value, write.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_And64(Atomic_uint64 *var, // IN
+             uint64 val)         // IN
+{
+#if defined(__x86_64__)
+#if defined(__GNUC__)
+   /* Checked against the AMD manual and GCC --hpreg */
+   __asm__ __volatile__(
+      "lock; andq %1, %0"
+      : "+m" (var->value)
+      : "ri" (val)
+      : "cc"
+   );
+   AtomicEpilogue();
+#elif defined _MSC_VER
+   _InterlockedAnd64((__int64 *)&var->value, (__int64)val);
+#else
+#error No compiler defined for Atomic_And64
+#endif
+#else // __x86_64__
+   uint64 oldVal;
+   uint64 newVal;
+   do {
+      oldVal = var->value;
+      newVal = oldVal & val;
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &newVal));
+#endif
+}
+
+
+/*
+ * Template code for the Atomic_<name> type and its operators.
+ *
+ * The cast argument is an intermedia type cast to make some
+ * compilers stop complaining about casting uint32 <-> void *,
+ * even though we only do it in the 32-bit case so they are always
+ * the same size.  So for val of type uint32, instead of
+ * (void *)val, we have (void *)(uintptr_t)val.
+ * The specific problem case is the Windows ddk compiler
+ * (as used by the SVGA driver).  -- edward
+ */
+
+#define MAKE_ATOMIC_TYPE(name, size, in, out, cast)                           \
+   typedef Atomic_uint ## size Atomic_ ## name;                               \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   AtomicAssertOnCompile ## name(void)                                        \
+   {                                                                          \
+      enum { AssertOnCompileMisused =    8 * sizeof (in) == size              \
+                                      && 8 * sizeof (out) == size             \
+                                      && 8 * sizeof (cast) == size            \
+                                         ? 1 : -1 };                          \
+      typedef char AssertOnCompileFailed[AssertOnCompileMisused];             \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_Read ## name(Atomic_ ## name const *var)                            \
+   {                                                                          \
+      return (out)(cast)Atomic_Read ## size(var);                             \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Write ## name(Atomic_ ## name *var,                                 \
+                        in val)                                               \
+   {                                                                          \
+      Atomic_Write ## size(var, (uint ## size)(cast)val);                     \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_ReadWrite ## name(Atomic_ ## name *var,                             \
+                            in val)                                           \
+   {                                                                          \
+      return (out)(cast)Atomic_ReadWrite ## size(var,                         \
+		(uint ## size)(cast)val);                                     \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_ReadIfEqualWrite ## name(Atomic_ ## name *var,                      \
+                                   in oldVal,                                 \
+                                   in newVal)                                 \
+   {                                                                          \
+      return (out)(cast)Atomic_ReadIfEqualWrite ## size(var,                  \
+                (uint ## size)(cast)oldVal, (uint ## size)(cast)newVal);      \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_And ## name(Atomic_ ## name *var,                                   \
+                      in val)                                                 \
+   {                                                                          \
+      Atomic_And ## size(var, (uint ## size)(cast)val);                       \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Or ## name(Atomic_ ## name *var,                                    \
+                     in val)                                                  \
+   {                                                                          \
+      Atomic_Or ## size(var, (uint ## size)(cast)val);                        \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Xor ## name(Atomic_ ## name *var,                                   \
+                      in val)                                                 \
+   {                                                                          \
+      Atomic_Xor ## size(var, (uint ## size)(cast)val);                       \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Add ## name(Atomic_ ## name *var,                                   \
+                      in val)                                                 \
+   {                                                                          \
+      Atomic_Add ## size(var, (uint ## size)(cast)val);                       \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Sub ## name(Atomic_ ## name *var,                                   \
+                      in val)                                                 \
+   {                                                                          \
+      Atomic_Sub ## size(var, (uint ## size)(cast)val);                       \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Inc ## name(Atomic_ ## name *var)                                   \
+   {                                                                          \
+      Atomic_Inc ## size(var);                                                \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE void                                                         \
+   Atomic_Dec ## name(Atomic_ ## name *var)                                   \
+   {                                                                          \
+      Atomic_Dec ## size(var);                                                \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_ReadOr ## name(Atomic_ ## name *var,                                \
+                         in val)                                              \
+   {                                                                          \
+      return (out)(cast)Atomic_ReadOr ## size(var, (uint ## size)(cast)val);  \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_ReadAdd ## name(Atomic_ ## name *var,                               \
+                          in val)                                             \
+   {                                                                          \
+      return (out)(cast)Atomic_ReadAdd ## size(var, (uint ## size)(cast)val); \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_ReadInc ## name(Atomic_ ## name *var)                               \
+   {                                                                          \
+      return (out)(cast)Atomic_ReadInc ## size(var);                          \
+   }                                                                          \
+                                                                              \
+                                                                              \
+   static INLINE out                                                          \
+   Atomic_ReadDec ## name(Atomic_ ## name *var)                               \
+   {                                                                          \
+      return (out)(cast)Atomic_ReadDec ## size(var);                          \
+   }
+
+
+/*
+ * Since we use a macro to generate these definitions, it is hard to look for
+ * them. So DO NOT REMOVE THIS COMMENT and keep it up-to-date. --hpreg
+ *
+ * Atomic_Ptr
+ * Atomic_ReadPtr --
+ * Atomic_WritePtr --
+ * Atomic_ReadWritePtr --
+ * Atomic_ReadIfEqualWritePtr --
+ * Atomic_AndPtr --
+ * Atomic_OrPtr --
+ * Atomic_XorPtr --
+ * Atomic_AddPtr --
+ * Atomic_SubPtr --
+ * Atomic_IncPtr --
+ * Atomic_DecPtr --
+ * Atomic_ReadOrPtr --
+ * Atomic_ReadAddPtr --
+ * Atomic_ReadIncPtr --
+ * Atomic_ReadDecPtr --
+ *
+ * Atomic_Int
+ * Atomic_ReadInt --
+ * Atomic_WriteInt --
+ * Atomic_ReadWriteInt --
+ * Atomic_ReadIfEqualWriteInt --
+ * Atomic_AndInt --
+ * Atomic_OrInt --
+ * Atomic_XorInt --
+ * Atomic_AddInt --
+ * Atomic_SubInt --
+ * Atomic_IncInt --
+ * Atomic_DecInt --
+ * Atomic_ReadOrInt --
+ * Atomic_ReadAddInt --
+ * Atomic_ReadIncInt --
+ * Atomic_ReadDecInt --
+ */
+#if defined(__x86_64__)
+MAKE_ATOMIC_TYPE(Ptr, 64, void const *, void *, uintptr_t)
+#else
+MAKE_ATOMIC_TYPE(Ptr, 32, void const *, void *, uintptr_t)
+#endif
+MAKE_ATOMIC_TYPE(Int, 32, int, int, int)
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_MFence --
+ *
+ *      Implements mfence in terms of a lock xor. The reason for implementing
+ *      our own mfence is that not all of our supported cpus have an assembly
+ *      mfence (P3, Athlon). We put it here to avoid duplicating code which is
+ *      also why it is prefixed with "Atomic_".
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Cause loads and stores prior to this to be globally
+ *      visible.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Atomic_MFence(void)
+{
+   Atomic_uint32 fence;
+   Atomic_Xor(&fence, 0x1);
+}
+
+#endif // ifndef _ATOMIC_H_
diff --git a/sys/dev/virtual/vmware/shared/vm_basic_asm.h b/sys/dev/virtual/vmware/shared/vm_basic_asm.h
new file mode 100644
index 0000000..3886f07
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_basic_asm.h
@@ -0,0 +1,1053 @@
+/*********************************************************
+ * Copyright (C) 2003-2011 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * vm_basic_asm.h
+ *
+ *	Basic asm macros
+ *
+ *        ARM not implemented.
+ */
+
+#ifndef _VM_BASIC_ASM_H_
+#define _VM_BASIC_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
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+#if defined VM_X86_64
+#include "vm_basic_asm_x86_64.h"
+#elif defined __i386__
+#include "vm_basic_asm_x86.h"
+#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.
+ */
+#ifdef _MSC_VER
+#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)
+
+#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  _bittestandset(long *, long);
+unsigned char  _bittestandreset(long *, long);
+#pragma intrinsic(_bittestandset, _bittestandreset)
+#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__ // {
+#if defined(__i386__) || defined(__x86_64__) // Only on x86*
+
+/*
+ * 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): );
+
+#endif // x86*
+
+#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
+
+#else // } {
+#error
+#endif // }
+
+/* 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))
+
+/*
+ * Locate most and least significant bit set functions. Use our own name
+ * space to avoid namespace collisions. The new names follow a pattern,
+ * <prefix><size><option>, where:
+ *
+ * <prefix> is [lm]ssb (least/most significant bit set)
+ * <size> is size of the argument: 32 (32-bit), 64 (64-bit) or Ptr (pointer)
+ * <option> is for alternative versions of the functions
+ *
+ * NAME        FUNCTION                    BITS     FUNC(0)
+ *-----        --------                    ----     -------
+ * lssb32_0    LSB set (uint32)            0..31    -1
+ * mssb32_0    MSB set (uint32)            0..31    -1
+ * lssb64_0    LSB set (uint64)            0..63    -1
+ * mssb64_0    MSB set (uint64)            0..63    -1
+ * lssbPtr_0   LSB set (uintptr_t;32-bit)  0..31    -1
+ * lssbPtr_0   LSB set (uintptr_t;64-bit)  0..63    -1
+ * mssbPtr_0   MSB set (uintptr_t;32-bit)  0..31    -1
+ * mssbPtr_0   MSB set (uintptr_t;64-bit)  0..63    -1
+ * lssbPtr     LSB set (uintptr_t;32-bit)  1..32    0
+ * lssbPtr     LSB set (uintptr_t;64-bit)  1..64    0
+ * mssbPtr     MSB set (uintptr_t;32-bit)  1..32    0
+ * mssbPtr     MSB set (uintptr_t;64-bit)  1..64    0
+ * lssb32      LSB set (uint32)            1..32    0
+ * mssb32      MSB set (uint32)            1..32    0
+ * lssb64      LSB set (uint64)            1..64    0
+ * mssb64      MSB set (uint64)            1..64    0
+ */
+
+#if defined(_MSC_VER)
+static INLINE int
+lssb32_0(const uint32 value)
+{
+   unsigned long idx;
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   }
+   _BitScanForward(&idx, (unsigned long) value);
+   return idx;
+}
+
+static INLINE int
+mssb32_0(const uint32 value)
+{
+   unsigned long idx;
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   }
+   _BitScanReverse(&idx, (unsigned long) value);
+   return idx;
+}
+
+static INLINE int
+lssb64_0(const uint64 value)
+{
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   } else {
+#if defined(VM_X86_64)
+      unsigned long idx;
+      _BitScanForward64(&idx, (unsigned __int64) value);
+      return idx;
+#else
+      /* The coding was chosen to minimize conditionals and operations */
+      int lowFirstBit = lssb32_0((uint32) value);
+      if (lowFirstBit == -1) {
+         lowFirstBit = lssb32_0((uint32) (value >> 32));
+         if (lowFirstBit != -1) {
+            return lowFirstBit + 32;
+         }
+      }
+      return lowFirstBit;
+#endif
+   }
+}
+
+static INLINE int
+mssb64_0(const uint64 value)
+{
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   } else {
+#if defined(VM_X86_64)
+      unsigned long idx;
+      _BitScanReverse64(&idx, (unsigned __int64) value);
+      return idx;
+#else
+      /* The coding was chosen to minimize conditionals and operations */
+      if (value > 0xFFFFFFFFULL) {
+         return 32 + mssb32_0((uint32) (value >> 32));
+      }
+      return mssb32_0((uint32) value);
+#endif
+   }
+}
+#endif
+
+#if defined(__GNUC__)
+#if defined(__i386__) || defined(__x86_64__) // Only on x86*
+#define USE_ARCH_X86_CUSTOM
+#endif
+
+static INLINE int
+lssb32_0(uint32 value)
+{
+#if defined(USE_ARCH_X86_CUSTOM)
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   } else {
+      int pos;
+      __asm__ __volatile__("bsfl %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
+      return pos;
+   }
+#else
+   return __builtin_ffs(value) - 1;
+#endif
+}
+
+static INLINE int
+mssb32_0(uint32 value)
+{
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   } else {
+      int pos;
+
+#if defined(USE_ARCH_X86_CUSTOM)
+      __asm__ __volatile__("bsrl %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
+#else
+      pos = 32 - __builtin_clz(value) - 1;
+#endif
+
+      return pos;
+   }
+}
+
+static INLINE int
+lssb64_0(const uint64 value)
+{
+#if defined(USE_ARCH_X86_CUSTOM)
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   } else {
+      intptr_t pos;
+
+#if defined(VM_X86_64)
+      __asm__ __volatile__("bsf %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
+#else
+      /* The coding was chosen to minimize conditionals and operations */
+      pos = lssb32_0((uint32) value);
+      if (pos == -1) {
+         pos = lssb32_0((uint32) (value >> 32));
+         if (pos != -1) {
+            return pos + 32;
+         }
+      }
+#endif
+
+      return pos;
+   }
+#else
+   return __builtin_ffsll(value) - 1;
+#endif
+}
+
+static INLINE int
+mssb64_0(const uint64 value)
+{
+   if (UNLIKELY(value == 0)) {
+      return -1;
+   } else {
+      intptr_t pos;
+
+#if defined(USE_ARCH_X86_CUSTOM)
+#if defined(VM_X86_64)
+      __asm__ __volatile__("bsr %1, %0\n" : "=r" (pos) : "rm" (value) : "cc");
+#else
+      /* The coding was chosen to minimize conditionals and operations */
+      if (value > 0xFFFFFFFFULL) {
+         pos = 32 + mssb32_0((uint32) (value >> 32));
+      } else {
+         pos = mssb32_0((uint32) value);
+      }
+#endif
+#else
+      pos = 64 - __builtin_clzll(value) - 1;
+#endif
+
+      return pos;
+   }
+}
+
+#if defined(USE_ARCH_X86_CUSTOM)
+#undef USE_ARCH_X86_CUSTOM
+#endif
+
+#endif
+
+static INLINE int
+lssbPtr_0(const uintptr_t value)
+{
+#if defined(VM_X86_64)
+   return lssb64_0((uint64) value);
+#else
+   return lssb32_0((uint32) value);
+#endif
+}
+
+static INLINE int
+lssbPtr(const uintptr_t value)
+{
+   return lssbPtr_0(value) + 1;
+}
+
+static INLINE int
+mssbPtr_0(const uintptr_t value)
+{
+#if defined(VM_X86_64)
+   return mssb64_0((uint64) value);
+#else
+   return mssb32_0((uint32) value);
+#endif
+}
+
+static INLINE int
+mssbPtr(const uintptr_t value)
+{
+   return mssbPtr_0(value) + 1;
+}
+
+static INLINE int
+lssb32(const uint32 value)
+{
+   return lssb32_0(value) + 1;
+}
+
+static INLINE int
+mssb32(const uint32 value)
+{
+   return mssb32_0(value) + 1;
+}
+
+static INLINE int
+lssb64(const uint64 value)
+{
+   return lssb64_0(value) + 1;
+}
+
+static INLINE int
+mssb64(const uint64 value)
+{
+   return mssb64_0(value) + 1;
+}
+
+#ifdef __GNUC__
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+
+static INLINE void *
+uint16set(void *dst, uint16 val, size_t count)
+{
+#ifdef __arm__
+   if (count <= 0)
+       return dst;
+   __asm__ __volatile__ ("\t"
+                         "1: strh %0, [%1]     \n\t"
+                         "   subs %2, %2, #1   \n\t"
+                         "   bne 1b                "
+                         :: "r" (val), "r" (dst), "r" (count)
+                         : "memory"
+        );
+   return dst;
+#else
+   int dummy0;
+   int dummy1;
+
+   __asm__ __volatile__("\t"
+                        "cld"            "\n\t"
+                        "rep ; stosw"    "\n"
+                        : "=c" (dummy0), "=D" (dummy1)
+                        : "0" (count), "1" (dst), "a" (val)
+                        : "memory", "cc"
+      );
+
+   return dst;
+#endif
+}
+
+static INLINE void *
+uint32set(void *dst, uint32 val, size_t count)
+{
+#ifdef __arm__
+   if (count <= 0)
+       return dst;
+   __asm__ __volatile__ ("\t"
+                         "1: str %0, [%1]     \n\t"
+                         "   subs %2, %2, #1  \n\t"
+                         "   bne 1b               "
+                         :: "r" (val), "r" (dst), "r" (count)
+                         : "memory"
+        );
+   return dst;
+#else
+   int dummy0;
+   int dummy1;
+
+   __asm__ __volatile__("\t"
+                        "cld"            "\n\t"
+                        "rep ; stosl"    "\n"
+                        : "=c" (dummy0), "=D" (dummy1)
+                        : "0" (count), "1" (dst), "a" (val)
+                        : "memory", "cc"
+      );
+
+   return dst;
+#endif
+}
+
+#else /* unknown system: rely on C to write */
+static INLINE void *
+uint16set(void *dst, uint16 val, size_t count)
+{
+   size_t i;
+   for (i = 0; i < count; i++) {
+     ((uint16 *) dst)[i] = val;
+   }
+   return dst;
+}
+
+static INLINE void *
+uint32set(void *dst, uint32 val, size_t count)
+{
+   size_t i;
+   for (i = 0; i < count; i++) {
+     ((uint32 *) dst)[i] = val;
+   }
+   return dst;
+}
+#endif // defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#elif defined(_MSC_VER)
+
+static INLINE void *
+uint16set(void *dst, uint16 val, size_t count)
+{
+#ifdef VM_X86_64
+   __stosw((uint16*)dst, val, count);
+#else
+   __asm { pushf;
+           mov ax, val;
+           mov ecx, count;
+           mov edi, dst;
+           cld;
+           rep stosw;
+           popf;
+   }
+#endif
+   return dst;
+}
+
+static INLINE void *
+uint32set(void *dst, uint32 val, size_t count)
+{
+#ifdef VM_X86_64
+   __stosd((unsigned long*)dst, (unsigned long)val, count);
+#else
+   __asm { pushf;
+           mov eax, val;
+           mov ecx, count;
+           mov edi, dst;
+           cld;
+           rep stosd;
+           popf;
+   }
+#endif
+   return dst;
+}
+
+#else
+#error "No compiler defined for uint*set"
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Bswap16 --
+ *
+ *      Swap the 2 bytes of "v" as follows: 32 -> 23.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+Bswap16(uint16 v)
+{
+   return ((v >> 8) & 0x00ff) | ((v << 8) & 0xff00);
+}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Bswap32 --
+ *
+ *      Swap the 4 bytes of "v" as follows: 3210 -> 0123.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint32
+Bswap32(uint32 v) // IN
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) || defined(__arm__) // {
+#ifdef __arm__
+    __asm__("rev %0, %0" : "+r"(v));
+    return v;
+#else // __arm__
+   /* Checked against the Intel manual and GCC. --hpreg */
+   __asm__(
+      "bswap %0"
+      : "=r" (v)
+      : "0" (v)
+   );
+   return v;
+#endif // !__arm__
+#else // } {
+   return    (v >> 24)
+          | ((v >>  8) & 0xFF00)
+          | ((v & 0xFF00) <<  8)
+          |  (v << 24)          ;
+#endif // }
+}
+#define Bswap Bswap32
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Bswap64 --
+ *
+ *      Swap the 8 bytes of "v" as follows: 76543210 -> 01234567.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Bswap64(uint64 v) // IN
+{
+   return ((uint64)Bswap((uint32)v) << 32) | Bswap((uint32)(v >> 32));
+}
+
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+/*
+ * COMPILER_MEM_BARRIER prevents the compiler from re-ordering memory
+ * references accross the barrier.  NOTE: It does not generate any
+ * instruction, so the CPU is free to do whatever it wants to...
+ */
+#ifdef __GNUC__ // {
+#define COMPILER_MEM_BARRIER()   __asm__ __volatile__ ("": : :"memory")
+#define COMPILER_READ_BARRIER()  COMPILER_MEM_BARRIER()
+#define COMPILER_WRITE_BARRIER() COMPILER_MEM_BARRIER()
+#elif defined(_MSC_VER)
+#define COMPILER_MEM_BARRIER()   _ReadWriteBarrier()
+#define COMPILER_READ_BARRIER()  _ReadBarrier()
+#define COMPILER_WRITE_BARRIER() _WriteBarrier()
+#endif // }
+
+
+/*
+ * PAUSE is a P4 instruction that improves spinlock power+performance;
+ * on non-P4 IA32 systems, the encoding is interpreted as a REPZ-NOP.
+ * Use volatile to avoid NOP removal.
+ */
+static INLINE void
+PAUSE(void)
+#ifdef __GNUC__
+{
+#ifdef __arm__
+   /*
+    * ARM has no instruction to execute "spin-wait loop", just leave it
+    * empty.
+    */
+#else
+   __asm__ __volatile__( "pause" :);
+#endif
+}
+#elif defined(_MSC_VER)
+#ifdef VM_X86_64
+{
+   _mm_pause();
+}
+#else /* VM_X86_64 */
+#pragma warning( disable : 4035)
+{
+   __asm _emit 0xf3 __asm _emit 0x90
+}
+#pragma warning (default: 4035)
+#endif /* VM_X86_64 */
+#else  /* __GNUC__  */
+#error No compiler defined for PAUSE
+#endif
+
+
+/*
+ * Checked against the Intel manual and GCC --hpreg
+ *
+ * volatile because the tsc always changes without the compiler knowing it.
+ */
+static INLINE uint64
+RDTSC(void)
+#ifdef __GNUC__
+{
+#ifdef VM_X86_64
+   uint64 tscLow;
+   uint64 tscHigh;
+
+   __asm__ __volatile__(
+      "rdtsc"
+      : "=a" (tscLow), "=d" (tscHigh)
+   );
+
+   return tscHigh << 32 | tscLow;
+#elif defined(__i386__)
+   uint64 tim;
+
+   __asm__ __volatile__(
+      "rdtsc"
+      : "=A" (tim)
+   );
+
+   return tim;
+#else
+   /*
+    * For platform without cheap timer, just return 0.
+    */
+   return 0;
+#endif
+}
+#elif defined(_MSC_VER)
+#ifdef VM_X86_64
+{
+   return __rdtsc();
+}
+#else
+#pragma warning( disable : 4035)
+{
+   __asm _emit 0x0f __asm _emit 0x31
+}
+#pragma warning (default: 4035)
+#endif /* VM_X86_64 */
+#else  /* __GNUC__  */
+#error No compiler defined for RDTSC
+#endif /* __GNUC__  */
+
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * 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
+}
+
+#endif // __i386 || __x86_64__
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * DEBUGBREAK --
+ *
+ *    Does an int3 for MSVC / GCC. This is a macro to make sure int3 is
+ *    always inlined.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifdef _MSC_VER
+#define DEBUGBREAK()   __debugbreak()
+#else
+#define DEBUGBREAK()   __asm__ (" int $3 ")
+#endif
+#endif // defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * {Clear,Set}Bit{32,64} --
+ *
+ *    Sets or clears a specified single bit in the provided variable.
+ *    The index input value specifies which bit to modify and is 0-based.
+ *    Index is truncated by hardware to a 5-bit or 6-bit offset for the
+ *    32 and 64-bit flavors, respectively, but input values are not validated
+ *    with asserts to avoid include dependencies.
+ *    64-bit flavors are not provided for 32-bit builds because the inlined
+ *    version can defeat user or compiler optimizations.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+SetBit32(uint32 *var, unsigned index)
+{
+#ifdef __GNUC__
+   __asm__ (
+      "bts %1, %0"
+      : "+mr" (*var)
+      : "ri" (index)
+      : "cc"
+   );
+#elif defined(_MSC_VER)
+   _bittestandset((long *)var, index);
+#endif
+}
+
+static INLINE void
+ClearBit32(uint32 *var, unsigned index)
+{
+#ifdef __GNUC__
+   __asm__ (
+      "btr %1, %0"
+      : "+mr" (*var)
+      : "ri" (index)
+      : "cc"
+   );
+#elif defined(_MSC_VER)
+   _bittestandreset((long *)var, index);
+#endif
+}
+
+#if defined(VM_X86_64)
+static INLINE void
+SetBit64(uint64 *var, unsigned index)
+{
+#ifdef __GNUC__
+   __asm__ (
+      "bts %1, %0"
+      : "+mr" (*var)
+      : "ri" (index)
+      : "cc"
+   );
+#elif defined _MSC_VER
+   _bittestandset64((__int64 *)var, index);
+#endif
+}
+
+static INLINE void
+ClearBit64(uint64 *var, unsigned index)
+{
+#ifdef __GNUC__
+   __asm__ (
+      "btr %1, %0"
+      : "+mr" (*var)
+      : "ri" (index)
+      : "cc"
+   );
+#elif defined _MSC_VER
+   _bittestandreset64((__int64 *)var, index);
+#endif
+}
+#endif /* VM_X86_64 */
+
+
+/*
+ *-----------------------------------------------------------------------------
+ * RoundUpPow2_{64,32} --
+ *
+ *   Rounds a value up to the next higher power of 2.  Returns the original
+ *   value if it is a power of 2.  The next power of 2 for inputs {0, 1} is 1.
+ *   The result is undefined for inputs above {2^63, 2^31} (but equal to 1
+ *   in this implementation).
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+RoundUpPow2C64(uint64 value)
+{
+   if (value <= 1 || value > (CONST64U(1) << 63)) {
+      return 1; // Match the assembly's undefined value for large inputs.
+   } else {
+      return (CONST64U(2) << mssb64_0(value - 1));
+   }
+}
+
+#if defined(VM_X86_64) && defined(__GNUC__)
+static INLINE uint64
+RoundUpPow2Asm64(uint64 value)
+{
+   uint64 out = 2;
+   __asm__("lea -1(%[in]), %%rcx;"      // rcx = value - 1.  Preserve original.
+           "bsr %%rcx, %%rcx;"          // rcx = log2(value - 1) if value != 1
+                                        // if value == 0, then rcx = 63
+                                        // if value == 1 then zf = 1, else zf = 0.
+           "rol %%cl, %[out];"          // out = 2 << rcx (if rcx != -1)
+                                        //     = 2^(log2(value - 1) + 1)
+                                        // if rcx == -1 (value == 0), out = 1
+                                        // zf is always unmodified.
+           "cmovz %[in], %[out]"        // if value == 1 (zf == 1), write 1 to out.
+       : [out]"+r"(out) : [in]"r"(value) : "%rcx", "cc");
+   return out;
+}
+#endif
+
+static INLINE uint64
+RoundUpPow2_64(uint64 value)
+{
+#if defined(VM_X86_64) && defined(__GNUC__)
+   if (__builtin_constant_p(value)) {
+      return RoundUpPow2C64(value);
+   } else {
+      return RoundUpPow2Asm64(value);
+   }
+#else
+   return RoundUpPow2C64(value);
+#endif
+}
+
+static INLINE uint32
+RoundUpPow2C32(uint32 value)
+{
+   if (value <= 1 || value > (1U << 31)) {
+      return 1; // Match the assembly's undefined value for large inputs.
+   } else {
+      return (2 << mssb32_0(value - 1));
+   }
+}
+
+#ifdef __GNUC__
+static INLINE uint32
+RoundUpPow2Asm32(uint32 value)
+{
+   uint32 out = 2;
+   __asm__("lea -1(%[in]), %%ecx;"      // ecx = value - 1.  Preserve original.
+           "bsr %%ecx, %%ecx;"          // ecx = log2(value - 1) if value != 1
+                                        // if value == 0, then ecx = 31
+                                        // if value == 1 then zf = 1, else zf = 0.
+           "rol %%cl, %[out];"          // out = 2 << ecx (if ecx != -1)
+                                        //     = 2^(log2(value - 1) + 1).
+                                        // if ecx == -1 (value == 0), out = 1
+                                        // zf is always unmodified
+           "cmovz %[in], %[out]"        // if value == 1 (zf == 1), write 1 to out.
+       : [out]"+r"(out) : [in]"r"(value) : "%ecx", "cc");
+   return out;
+}
+#endif // __GNUC__
+
+static INLINE uint32
+RoundUpPow2_32(uint32 value)
+{
+#ifdef __GNUC__
+   if (__builtin_constant_p(value)) {
+      return RoundUpPow2C32(value);
+   } else {
+      return RoundUpPow2Asm32(value);
+   }
+#else
+   return RoundUpPow2C32(value);
+#endif
+}
+
+#endif // _VM_BASIC_ASM_H_
diff --git a/sys/dev/virtual/vmware/shared/vm_basic_asm_x86.h b/sys/dev/virtual/vmware/shared/vm_basic_asm_x86.h
new file mode 100644
index 0000000..e4849ab
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_basic_asm_x86.h
@@ -0,0 +1,570 @@
+/*********************************************************
+ * Copyright (C) 1998-2003 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+#ifdef VM_X86_64
+/*
+ * The gcc inline asm uses the "A" constraint which differs in 32 & 64
+ * bit mode.  32 bit means eax and edx, 64 means rax or rdx.
+ */
+#error "x86-64 not supported"
+#endif
+
+
+/*
+ * 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(). --hpreg
+ *
+ * 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
+{
+   /* Checked against the Intel manual and GCC --hpreg */
+   __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
+{
+   /* Written and tested by mann, checked by dbudko and hpreg */
+   __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 --hpreg
+ *
+ * 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;
+
+   /* Checked against the Intel manual and GCC --hpreg */
+   __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:
+ *       Unsigned 64-bit integer multiplicand.
+ *       Unsigned 32-bit fixed point multiplier, represented as
+ *         multiplier >> shift, where shift < 64.
+ *       Unsigned 64-bit integer product.
+ *
+ * Implementation:
+ *    Multiply 64x32 bits to yield a full 96-bit product.
+ *    Shift right by shift.
+ *    Return the low-order 64 bits of the result.
+ *
+ * Result:
+ *    Product
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__)
+
+static INLINE uint64
+Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
+{
+   uint64 result;
+   uint32 tmp1, tmp2;
+   // ASSERT(shift >= 0 && shift < 64);
+
+   /*
+    * Written and tested by mann, improved with suggestions by hpreg.
+    *
+    * The main improvement over the previous version is that the test
+    * of shift against 32 is moved out of the asm and into C code.
+    * This lets the compiler delete the test and one of the
+    * alternative code sequences in the case where shift is a
+    * constant.  It also lets us use the best code sequence in each
+    * alternative, rather than a compromise.  The downside is that in
+    * the non-constant case, this version takes slightly more code
+    * space.
+    *
+    * Note on the constraints: We don't really want multiplicand to
+    * start in %edx:%eax as the =A constraint dictates; in fact, we'd
+    * prefer any *other* two registers.  But gcc doesn't have
+    * constraint syntax for any other register pair, and trying to
+    * constrain ((uint32) multiplicand) to one place and (multiplicand
+    * >> 32) to another generates *really* bad code -- gcc is just not
+    * smart enough, at least in the version we are currently using.
+    */
+   if (shift < 32) {
+      __asm__("mov   %%eax, %2     \n\t" // Save lo(multiplicand) in tmp2
+              "mov   %%edx, %%eax  \n\t" // Get hi(multiplicand)
+              "mull  %4            \n\t" // p2 = hi(multiplicand) * multiplier
+              "xchg  %%eax, %2     \n\t" // Save lo(p2) in tmp2, get lo(multiplicand)
+              "mov   %%edx, %1     \n\t" // Save hi(p2) in tmp1
+              "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
+              "shrdl %%edx, %%eax  \n\t" // result = hi(p2):hi(p1):lo(p1) >> shift
+              "shrdl %1, %%edx"
+              : "=A"  (result),
+                "=&r" (tmp1),            // use in shrdl requires it to be a register
+                "=&r" (tmp2)             // could be "=&rm" but "m" is slower
+              : "0"   (multiplicand),
+                "rm"  (multiplier),
+                "c"   (shift)
+              : "cc"
+         );
+   } else {
+      __asm__("mov   %%edx, %2     \n\t" // Save hi(multiplicand) in tmp2
+              "mull  %4            \n\t" // p1 = lo(multiplicand) * multiplier
+              "mov   %%edx, %1     \n\t" // Save hi(p1) in tmp1
+              "mov   %2, %%eax     \n\t" // Discard lo(p1), get hi(multiplicand)
+              "mull  %4            \n\t" // p2 = hi(multiplicand) * multiplier
+              "addl  %1, %%eax     \n\t" // lo(p2) += hi(p1)
+              "adcl  $0, %%edx     \n\t" // hi(p2) += carry from previous step
+              "shrdl %%edx, %%eax  \n\t" // result = p2 >> (shift & 31)
+              "shrl  %%cl, %%edx"
+              : "=A"  (result),
+                "=&r" (tmp1),            // could be "=&rm" but "m" is slower
+                "=&r" (tmp2)             // could be "=&rm" but "m" is slower
+              : "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);
+
+   /* Written and tested by mann, checked by dbudko and hpreg */
+   __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
+      mov  eax, edx                         // result = hi(p2):hi(p1) >> (shift & 31)
+      mov  edx, ebx
+      shrd eax, edx, cl
+      shr  edx, cl
+      jmp  SHORT l3
+   l2:
+      shrd eax, edx, cl                     // result = hi(p2):hi(p1):lo(p1) >> shift
+      shrd edx, ebx, cl
+   l3:
+   }
+   // return with result in edx:eax
+}
+
+#pragma warning(default: 4035)
+#else
+#error No compiler defined for Mul64x3264
+#endif
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Muls64x32s64 --
+ *
+ *    Signed integer by fixed point multiplication:
+ *       Signed 64-bit integer multiplicand.
+ *       Unsigned 32-bit fixed point multiplier, represented as
+ *         multiplier >> shift, where shift < 64.
+ *       Signed 64-bit integer product.
+ *
+ * Implementation:
+ *    Multiply 64x32 bits to yield a full 96-bit product.
+ *    Shift right by the location of the binary point.
+ *    Return the low-order 64 bits of the result.
+ *
+ * Result:
+ *    Product
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__)
+
+static INLINE int64
+Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
+{
+   int64 result;
+   uint32 tmp1, tmp2;
+   // ASSERT(shift >= 0 && shift < 64);
+
+   /* Written and tested by mann, checked by dbudko and hpreg */
+   /* XXX hpreg suggested some improvements that we haven't converged on yet */
+   __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
+           "mov   %%edx, %%eax\n\t"   // result = hi(p2):hi(p1) >> (shift & 31)
+           "mov   %1, %%edx\n\t"
+           "shrdl %%edx, %%eax\n\t"
+           "sarl  %%cl, %%edx\n\t"
+           "jmp   3f\n"
+        "2:\n\t"
+           "shrdl %%edx, %%eax\n\t"   // result = hi(p2):hi(p1):lo(p1) >> shift
+           "shrdl %1, %%edx\n"
+        "3:\n\t"
+           : "=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);
+
+   /* Written and tested by mann, checked by dbudko and hpreg */
+   __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
+      mov  eax, edx                         // result = hi(p2):hi(p1) >> (shift & 31)
+      mov  edx, ebx
+      shrd eax, edx, cl
+      sar  edx, cl
+      jmp  SHORT l3
+   l2:
+      shrd eax, edx, cl                     // result = hi(p2):hi(p1):lo(p1) << shift
+      shrd edx, ebx, cl
+   l3:
+   }
+   // return with result in edx:eax
+}
+
+#pragma warning(default: 4035)
+#else
+#error No compiler defined for Muls64x32s64
+#endif
+
+
+#endif
diff --git a/sys/dev/virtual/vmware/shared/vm_basic_asm_x86_64.h b/sys/dev/virtual/vmware/shared/vm_basic_asm_x86_64.h
new file mode 100644
index 0000000..b3e377e
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_basic_asm_x86_64.h
@@ -0,0 +1,553 @@
+/*********************************************************
+ * Copyright (C) 1998-2004 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
+
+#ifdef _MSC_VER
+
+#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
+
+/*
+ * GET_CURRENT_RIP
+ *
+ * Return an approximation of the current instruction pointer. For example for a
+ * function call
+ * foo.c
+ * L123: Foo(GET_CURRENT_RIP())
+ *
+ * The return value from GET_CURRENT_RIP will point a debugger to L123.
+ */
+#if defined(__GNUC__)
+#define GET_CURRENT_RIP() ({                                                   \
+      void *__rip;                                                             \
+      asm("lea 0(%%rip), %0;\n\t"                                              \
+         : "=r" (__rip));                                                      \
+      __rip;                                                                   \
+})
+#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__ */
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Mul64x6464 --
+ *
+ *    Unsigned integer by fixed point multiplication:
+ *       result = multiplicand * multiplier >> shift
+ *
+ *       Unsigned 64-bit integer multiplicand.
+ *       Unsigned 64-bit fixed point multiplier, represented as
+ *         multiplier >> shift, where shift < 64.
+ *       Unsigned 64-bit integer product.
+ *
+ * Implementation:
+ *    Multiply 64x64 bits to yield a full 128-bit product.
+ *    Shift result in RDX:RAX right by "shift".
+ *    Return the low-order 64 bits of the above.
+ *
+ * Result:
+ *    Product
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__)
+
+static INLINE uint64
+Mul64x6464(uint64 multiplicand,
+           uint64 multiplier,
+           uint32 shift)
+{
+   uint64 result, dummy;
+
+   __asm__("mulq    %3      \n\t"
+           "shrdq   %1, %0  \n\t"
+           : "=a" (result),
+             "=d" (dummy)
+           : "0"  (multiplier),
+             "rm" (multiplicand),
+         "c"  (shift)
+           : "cc");
+   return result;
+}
+
+#elif defined(_MSC_VER)
+
+static INLINE uint64
+Mul64x6464(uint64 multiplicand, uint64 multiplier, uint32 shift)
+{
+   uint64 tmplo, tmphi;
+   tmplo = _umul128(multiplicand, multiplier, &tmphi);
+   return __shiftright128(tmplo, tmphi, (uint8) shift);
+}
+
+#endif
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Muls64x64s64 --
+ *
+ *    Signed integer by fixed point multiplication:
+ *       result = multiplicand * multiplier >> shift
+ *
+ *       Signed 64-bit integer multiplicand.
+ *       Unsigned 64-bit fixed point multiplier, represented as
+ *         multiplier >> shift, where shift < 64.
+ *       Signed 64-bit integer product.
+ *
+ * Implementation:
+ *    Multiply 64x64 bits to yield a full 128-bit product.
+ *    Shift result in RDX:RAX right by "shift".
+ *    Return the low-order 64 bits of the above.
+ *
+ *    Note: using an unsigned shift instruction is correct because
+ *    shift < 64 and we return only the low 64 bits of the shifted
+ *    result.
+ *
+ * Result:
+ *    Product
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__)
+
+static inline int64
+Muls64x64s64(int64 multiplicand, int64 multiplier, uint32 shift)
+{
+   int64 result, dummy;
+
+   __asm__("imulq   %3      \n\t"
+       "shrdq   %1, %0  \n\t"
+       : "=a" (result),
+         "=d" (dummy)
+       : "0"  (multiplier),
+         "rm" (multiplicand),
+         "c"  (shift)
+       : "cc");
+   return result;
+}
+
+#elif defined(_MSC_VER)
+
+static INLINE int64
+Muls64x64s64(int64 multiplicand, int64 multiplier, uint32 shift)
+{
+   int64 tmplo, tmphi;
+
+   tmplo = _mul128(multiplicand, multiplier, &tmphi);
+   return __shiftright128(tmplo, tmphi, (uint8) shift);
+}
+
+#endif
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Mul64x3264 --
+ *
+ *    Unsigned integer by fixed point multiplication:
+ *       result = multiplicand * multiplier >> shift
+ *
+ *       Unsigned 64-bit integer multiplicand.
+ *       Unsigned 32-bit fixed point multiplier, represented as
+ *         multiplier >> shift, where shift < 64.
+ *       Unsigned 64-bit integer product.
+ *
+ * Implementation:
+ *    Multiply 64x64 bits to yield a full 128-bit product.
+ *    Shift result in RDX:RAX right by "shift".
+ *    Return the low-order 64 bits of the above.
+ *
+ * Result:
+ *    Return the low-order 64 bits of ((multiplicand * multiplier) >> shift)
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE uint64
+Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
+{
+   return Mul64x6464(multiplicand, multiplier, shift);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Muls64x32s64 --
+ *
+ *    Signed integer by fixed point multiplication:
+ *       result = (multiplicand * multiplier) >> shift
+ *
+ *       Signed 64-bit integer multiplicand.
+ *       Unsigned 32-bit fixed point multiplier, represented as
+ *         multiplier >> shift, where shift < 64.
+ *       Signed 64-bit integer product.
+ *
+ * Implementation:
+ *    Multiply 64x64 bits to yield a full 128-bit product.
+ *    Shift result in RDX:RAX right by "shift".
+ *    Return the low-order 64 bits of the above.
+ *
+ * Result:
+ *    Return the low-order 64 bits of ((multiplicand * multiplier) >> shift)
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE int64
+Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
+{
+   return Muls64x64s64(multiplicand, multiplier, shift);
+}
+
+
+#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_
diff --git a/sys/dev/virtual/vmware/shared/vm_basic_defs.h b/sys/dev/virtual/vmware/shared/vm_basic_defs.h
new file mode 100644
index 0000000..8bab751
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_basic_defs.h
@@ -0,0 +1,660 @@
+/*********************************************************
+ * Copyright (C) 2003-2010 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+#include "vm_basic_types.h" // For INLINE.
+
+/* Checks for FreeBSD, filtering out VMKERNEL. */
+//#define __IS_FREEBSD__ (!defined(VMKERNEL) && defined(__FreeBSD__))
+//#define __IS_FREEBSD_VER__(ver) (__IS_FREEBSD__ && __FreeBSD_version >= (ver))
+
+#if defined _WIN32 && defined USERLEVEL
+   #include <stddef.h>  /*
+                         * We redefine offsetof macro from stddef; make
+                         * sure that it's already defined before we do that.
+                         */
+   #include <windows.h>	// for Sleep() and LOWORD() etc.
+   #undef GetFreeSpace  // Unpollute preprocessor namespace.
+#endif
+
+
+/*
+ * Simple macros
+ */
+
+#if (defined __APPLE__ || defined __FreeBSD__) && \
+    (!defined KERNEL && !defined _KERNEL && !defined VMKERNEL && !defined __KERNEL__)
+#   include <stddef.h>
+#else
+// XXX the _WIN32 one matches that of VC++, to prevent redefinition warning
+// XXX the other one matches that of gcc3.3.3/glibc2.2.4 to prevent redefinition warnings
+#ifndef offsetof
+#ifdef _WIN32
+#define offsetof(s,m)   (size_t)&(((s *)0)->m)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#endif
+#endif // __APPLE__
+
+#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 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 */
+
+#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.
+ */
+
+#define WSTR_(X)     L ## X
+#define WSTR(X)      WSTR_(X)
+
+
+/*
+ * 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 __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 VM_PAGE_BASE
+#define VM_PAGE_BASE(_addr)  ((_addr)&~(PAGE_SIZE-1))
+#endif
+
+#ifndef VM_PAGES_SPANNED
+#define VM_PAGES_SPANNED(_addr, _size) \
+   ((((_addr) & (PAGE_SIZE - 1)) + (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+#endif
+
+#ifndef BYTES_2_PAGES
+#define BYTES_2_PAGES(_nbytes)  ((_nbytes) >> PAGE_SHIFT)
+#endif
+
+#ifndef PAGES_2_BYTES
+#define PAGES_2_BYTES(_npages)  (((uint64)(_npages)) << PAGE_SHIFT)
+#endif
+
+#ifndef MBYTES_2_PAGES
+#define MBYTES_2_PAGES(_nbytes) ((_nbytes) << (20 - PAGE_SHIFT))
+#endif
+
+#ifndef PAGES_2_MBYTES
+#define PAGES_2_MBYTES(_npages) ((_npages) >> (20 - PAGE_SHIFT))
+#endif
+
+#ifndef BYTES_2_MBYTES
+#define BYTES_2_MBYTES(_nbytes) ((_nbytes) >> 20)
+#endif
+
+#ifndef MBYTES_2_BYTES
+#define MBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << 20)
+#endif
+
+#ifndef 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 NR_MPNS_PER_PAGE
+#define NR_MPNS_PER_PAGE (PAGE_SIZE / sizeof(MPN))
+#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
+
+#define HIDWORD(_qw)   ((uint32)((_qw) >> 32))
+#define LODWORD(_qw)   ((uint32)(_qw))
+#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
+
+static INLINE_SINGLE_CALLER uintptr_t
+GetFrameAddr(void)
+{
+   uintptr_t bp;
+#if  !(__GNUC__ == 4 && (__GNUC_MINOR__ == 0 || __GNUC_MINOR__ == 1))
+   bp = (uintptr_t)__builtin_frame_address(0);
+#else
+   /*
+    * We use this assembly hack due to a bug discovered in gcc 4.1.1.
+    * The bug was fixed in 4.2.0; assume it originated with 4.0.
+    * PR147638, PR554369.
+    */
+     __asm__ __volatile__(
+#  if defined(VM_X86_64)
+                          "movq %%rbp, %0\n"
+#  else
+                          "movl %%ebp, %0\n"
+#  endif
+                          : "=g" (bp));
+#endif
+   return bp;
+}
+
+
+/*
+ * Returns the frame pointer of the calling function.
+ * Equivalent to __builtin_frame_address(1).
+ */
+static INLINE_SINGLE_CALLER uintptr_t
+GetCallerFrameAddr(void)
+{
+   return *(uintptr_t*)GetFrameAddr();
+}
+
+#endif // sun
+#endif // __GNUC__
+
+/*
+ * Data prefetch was added in gcc 3.1.1
+ * http://www.gnu.org/software/gcc/gcc-3.1/changes.html
+ */
+#ifdef __GNUC__
+#  if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 1) || \
+       (__GNUC__ == 3 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 1))
+#     define PREFETCH_R(var) __builtin_prefetch((var), 0 /* read */, \
+                                                3 /* high temporal locality */)
+#     define PREFETCH_W(var) __builtin_prefetch((var), 1 /* write */, \
+                                                3 /* high temporal locality */)
+#  else
+#     define PREFETCH_R(var) ((void)(var))
+#     define PREFETCH_W(var) ((void)(var))
+#  endif
+#endif /* __GNUC__ */
+
+
+#ifdef USERLEVEL // {
+
+/*
+ * Note this might be a problem on NT b/c while sched_yield guarantees it
+ * moves you to the end of your priority list, Sleep(0) offers no such
+ * guarantee.  Bummer.  --Jeremy.
+ */
+
+#if defined(N_PLAT_NLM)
+/* We do not have YIELD() as we do not need it yet... */
+#elif defined(_WIN32)
+#      define YIELD()		Sleep(0)
+#else
+#      include <sched.h>        // For sched_yield.  Don't ask.  --Jeremy.
+#      define YIELD()		sched_yield()
+#endif
+
+
+/*
+ * Standardize some Posix names on Windows.
+ */
+
+#ifdef _WIN32 // {
+
+#define snprintf  _snprintf
+#define strtok_r  strtok_s
+
+#if (_MSC_VER < 1500)
+#define	vsnprintf _vsnprintf
+#endif
+
+typedef int uid_t;
+typedef int gid_t;
+
+static INLINE void
+sleep(unsigned int sec)
+{
+   Sleep(sec * 1000);
+}
+
+static INLINE void
+usleep(unsigned long usec)
+{
+   Sleep(CEILING(usec, 1000));
+}
+
+typedef int pid_t;
+#define       F_OK          0
+#define       X_OK          1
+#define       W_OK          2
+#define       R_OK          4
+
+#endif // }
+
+/*
+ * Macro for username comparison.
+ */
+
+#ifdef _WIN32 // {
+#define USERCMP(x,y)  Str_Strcasecmp(x,y)
+#else
+#define USERCMP(x,y)  strcmp(x,y)
+#endif // }
+
+
+#endif // }
+
+#ifndef va_copy
+
+#ifdef _WIN32
+
+/*
+ * Windows needs va_copy. This works for both 32 and 64-bit Windows
+ * based on inspection of how varags.h from the Visual C CRTL is
+ * implemented. (Future versions of the RTL may break this).
+ */
+
+#define va_copy(dest, src) ((dest) = (src))
+
+#elif defined(__APPLE__) && defined(KERNEL)
+
+#include "availabilityMacOS.h"
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+// The Mac OS 10.5 kernel SDK defines va_copy in stdarg.h.
+#include <stdarg.h>
+#else
+/*
+ * The Mac OS 10.4 kernel SDK needs va_copy. Based on inspection of
+ * stdarg.h from the MacOSX10.4u.sdk kernel framework, this should
+ * work.
+ */
+#define va_copy(dest, src) ((dest) = (src))
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED
+
+#elif defined(__GNUC__) && (__GNUC__ < 3)
+
+/*
+ * Old versions of gcc recognize __va_copy, but not va_copy.
+ */
+
+#define va_copy(dest, src) __va_copy(dest, src)
+
+#endif // _WIN32
+
+#endif // va_copy
+
+/*
+ * This one is outside USERLEVEL because it's used by
+ * files compiled into the Windows hgfs driver or the display
+ * driver.
+ */
+
+#ifdef _WIN32
+#define PATH_MAX 256
+#ifndef strcasecmp
+#define strcasecmp(_s1,_s2)   _stricmp((_s1),(_s2))
+#endif
+#ifndef strncasecmp
+#define strncasecmp(_s1,_s2,_n)   _strnicmp((_s1),(_s2),(_n))
+#endif
+#endif
+
+#if defined __linux__ && !defined __KERNEL__ && !defined MODULE && \
+                         !defined VMM && !defined FROBOS && !defined __ANDROID__
+#include <features.h>
+#if __GLIBC_PREREQ(2, 1) && !defined GLIBC_VERSION_21
+#define GLIBC_VERSION_21
+#endif
+#if __GLIBC_PREREQ(2, 2) && !defined GLIBC_VERSION_22
+#define GLIBC_VERSION_22
+#endif
+#if __GLIBC_PREREQ(2, 3) && !defined GLIBC_VERSION_23
+#define GLIBC_VERSION_23
+#endif
+#if __GLIBC_PREREQ(2, 4) && !defined GLIBC_VERSION_24
+#define GLIBC_VERSION_24
+#endif
+#if __GLIBC_PREREQ(2, 5) && !defined GLIBC_VERSION_25
+#define GLIBC_VERSION_25
+#endif
+#endif
+
+/*
+ * Convenience macros and definitions. Can often be used instead of #ifdef.
+ */
+
+#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_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 VMX86_WGS
+#define vmx86_wgs 1
+#define WGS_ONLY(x) x
+#else
+#define vmx86_wgs 0
+#define WGS_ONLY(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)
+#else
+#define WIN32_ONLY(x)
+#define POSIX_ONLY(x) x
+#endif
+
+#ifdef __linux__
+#define LINUX_ONLY(x) x
+#else
+#define LINUX_ONLY(x)
+#endif
+
+#ifdef __APPLE__
+#define vmx86_apple 1
+#define APPLE_ONLY(x) x
+#else
+#define vmx86_apple 0
+#define APPLE_ONLY(x)
+#endif
+
+#ifdef VMM
+#define VMM_ONLY(x) x
+#define USER_ONLY(x)
+#else
+#define VMM_ONLY(x)
+#define USER_ONLY(x) x
+#endif
+
+/* VMVISOR ifdef only allowed in the vmkernel */
+#ifdef VMKERNEL
+#ifdef VMVISOR
+#define vmvisor 1
+#define VMVISOR_ONLY(x) x
+#else
+#define vmvisor 0
+#define VMVISOR_ONLY(x)
+#endif
+#endif
+
+#ifdef _WIN32
+#define VMW_INVALID_HANDLE INVALID_HANDLE_VALUE
+#else
+#define VMW_INVALID_HANDLE (-1LL)
+#endif
+
+#ifdef _WIN32
+#define fsync(fd) _commit(fd)
+#define fileno(f) _fileno(f)
+#else
+#endif
+
+/*
+ * Debug output macros for Windows drivers (the Eng variant is for
+ * display/printer drivers only.
+ */
+#ifdef _WIN32
+#ifndef USES_OLD_WINDDK
+#if defined(VMX86_LOG)
+#define WinDrvPrint(arg, ...) DbgPrint(arg, __VA_ARGS__)
+#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)
+
+#endif // ifndef _VM_BASIC_DEFS_H_
diff --git a/sys/dev/virtual/vmware/shared/vm_basic_math.h b/sys/dev/virtual/vmware/shared/vm_basic_math.h
new file mode 100644
index 0000000..78d8d7f
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_basic_math.h
@@ -0,0 +1,78 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+#include "vm_basic_types.h" // For INLINE.
+#include "vm_basic_asm.h"   // For Div64...
+
+
+static INLINE uint32
+RatioOf(uint32 numer1, uint32 numer2, uint32 denom)
+{
+   uint64 numer = (uint64)numer1 * numer2;
+   /* Calculate "(numer1 * numer2) / denom" avoiding round-off errors. */
+#if defined(VMM) || !(defined(__i386__) || defined(__x86_64__))
+   return numer / denom;
+#else
+   uint32 ratio;
+   uint32 unused;
+   Div643232(numer, denom, &ratio, &unused);
+   return ratio;
+#endif
+}
+
+static INLINE uint32
+ExponentialAvg(uint32 avg, uint32 value, uint32 gainNumer, uint32 gainDenom)
+{
+   uint32 term1 = gainNumer * avg;
+   uint32 term2 = (gainDenom - gainNumer) * value;
+   return (term1 + term2) / gainDenom;
+}
+
+#endif // ifndef _VM_BASIC_MATH_H_
diff --git a/sys/dev/virtual/vmware/shared/vm_basic_types.h b/sys/dev/virtual/vmware/shared/vm_basic_types.h
new file mode 100644
index 0000000..06d9c83
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_basic_types.h
@@ -0,0 +1,1004 @@
+/*********************************************************
+ * Copyright (C) 1998-2009 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ *
+ * vm_basic_types.h --
+ *
+ *    basic data types.
+ */
+
+
+#ifndef _VM_BASIC_TYPES_H_
+#define _VM_BASIC_TYPES_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
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+/* STRICT ANSI means the Xserver build and X defines Bool differently. */
+#if !defined(_XTYPEDEF_BOOL) && \
+    (!defined(__STRICT_ANSI__) || defined(__DragonFly__) || defined(__MINGW32__))
+#define _XTYPEDEF_BOOL
+typedef char           Bool;
+#endif
+
+#ifndef FALSE
+#define FALSE          0
+#endif
+
+#ifndef TRUE
+#define TRUE           1
+#endif
+
+#define IsBool(x)      (((x) & ~1) == 0)
+#define IsBool2(x, y)  ((((x) | (y)) & ~1) == 0)
+
+/*
+ * Macros __i386__ and __ia64 are intrinsically defined by GCC
+ */
+#if defined _MSC_VER && defined _M_X64
+#  define __x86_64__
+#elif defined _MSC_VER && defined _M_IX86
+#  define __i386__
+#endif
+
+#ifdef __i386__
+#define VM_I386
+#endif
+
+#ifdef __x86_64__
+#define VM_X86_64
+#define VM_I386
+#define vm_x86_64 (1)
+#else
+#define vm_x86_64 (0)
+#endif
+
+
+#ifdef _MSC_VER
+
+#pragma warning (3 :4505) // unreferenced local function
+#pragma warning (disable :4018) // signed/unsigned mismatch
+#pragma warning (disable :4761) // integral size mismatch in argument; conversion supplied
+#pragma warning (disable :4305) // truncation from 'const int' to 'short'
+#pragma warning (disable :4244) // conversion from 'unsigned short' to 'unsigned char'
+#pragma warning (disable :4267) // truncation of 'size_t'
+#pragma warning (disable :4146) // unary minus operator applied to unsigned type, result still unsigned
+#pragma warning (disable :4142) // benign redefinition of type
+
+#endif
+
+#if defined(__APPLE__) || defined(HAVE_STDINT_H)
+
+/*
+ * TODO: This is a C99 standard header.  We should be able to test for
+ * #if __STDC_VERSION__ >= 199901L, but that breaks the Netware build
+ * (which doesn't have stdint.h).
+ */
+
+#include <stdint.h>
+
+typedef uint64_t    uint64;
+typedef  int64_t     int64;
+typedef uint32_t    uint32;
+typedef  int32_t     int32;
+typedef uint16_t    uint16;
+typedef  int16_t     int16;
+typedef  uint8_t    uint8;
+typedef   int8_t     int8;
+
+/*
+ * Note: C does not specify whether char is signed or unsigned, and
+ * both gcc and msvc implement processor-specific signedness.  With
+ * three types:
+ * typeof(char) != typeof(signed char) != typeof(unsigned char)
+ *
+ * Be careful here, because gcc (4.0.1 and others) likes to warn about
+ * conversions between signed char * and char *.
+ */
+
+#else /* !HAVE_STDINT_H */
+
+#ifdef _MSC_VER
+
+typedef unsigned __int64 uint64;
+typedef signed __int64 int64;
+
+#elif __GNUC__
+/* The Xserver source compiles with -ansi -pendantic */
+#   if !defined(__STRICT_ANSI__) || defined(__DragonFly__)
+#      if defined(VM_X86_64)
+typedef unsigned long uint64;
+typedef long int64;
+#      else
+typedef unsigned long long uint64;
+typedef long long int64;
+#      endif
+#   endif
+#else
+#   error - Need compiler define for int64/uint64
+#endif /* _MSC_VER */
+
+typedef unsigned int       uint32;
+typedef unsigned short     uint16;
+typedef unsigned char      uint8;
+
+typedef int                int32;
+typedef short              int16;
+typedef signed char        int8;
+
+#endif /* HAVE_STDINT_H */
+
+/*
+ * FreeBSD (for the tools build) unconditionally defines these in
+ * sys/inttypes.h so don't redefine them if this file has already
+ * been included. [greg]
+ *
+ * This applies to Solaris as well.
+ */
+
+/*
+ * Before trying to do the includes based on OS defines, see if we can use
+ * feature-based defines to get as much functionality as possible
+ */
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_INTTYPES_H
+#include <sys/inttypes.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef __DragonFly__
+#include <sys/param.h> /* For __FreeBSD_version */
+#endif
+
+#if !defined(USING_AUTOCONF)
+#   if defined(__DragonFly__) || defined(sun)
+#      ifdef KLD_MODULE
+#         include <sys/types.h>
+#      else
+#         ifdef __DragonFly__
+#            if !defined(VMKERNEL)
+#               include <inttypes.h>
+#            endif
+#            include <sys/types.h>
+#         else
+#            include <sys/inttypes.h>
+#         endif
+#      endif
+#   elif defined __APPLE__
+#      if KERNEL
+#         include <sys/unistd.h>
+#         include <sys/types.h> /* mostly for size_t */
+#         include <stdint.h>
+#      else
+#         include <unistd.h>
+#         include <inttypes.h>
+#         include <stdlib.h>
+#         include <stdint.h>
+#      endif
+#   elif defined __ANDROID__
+#      include <stdint.h>
+#   else
+#      if !defined(__intptr_t_defined) && !defined(intptr_t)
+#         ifdef VM_I386
+#         define __intptr_t_defined
+#            ifdef VM_X86_64
+typedef int64     intptr_t;
+#            else
+typedef int32     intptr_t;
+#            endif
+#         elif defined(__arm__)
+typedef int32     intptr_t;
+#         endif
+#      endif
+
+#      ifndef _STDINT_H
+#         ifdef VM_I386
+#            ifdef VM_X86_64
+typedef uint64    uintptr_t;
+#            else
+typedef uint32    uintptr_t;
+#            endif
+#         elif defined(__arm__)
+typedef uint32    uintptr_t;
+#         endif
+#      endif
+#   endif
+#endif
+
+
+/*
+ * Time
+ * XXX These should be cleaned up.  -- edward
+ */
+
+typedef int64 VmTimeType;          /* Time in microseconds */
+typedef int64 VmTimeRealClock;     /* Real clock kept in microseconds */
+typedef int64 VmTimeVirtualClock;  /* Virtual Clock kept in CPU cycles */
+
+/*
+ * Printf format specifiers for size_t and 64-bit number.
+ * Use them like this:
+ *    printf("%"FMT64"d\n", big);
+ *
+ * FMTH is for handles/fds.
+ */
+
+#ifdef _MSC_VER
+   #define FMT64      "I64"
+   #ifdef VM_X86_64
+      #define FMTSZ      "I64"
+      #define FMTPD      "I64"
+      #define FMTH       "I64"
+   #else
+      #define FMTSZ      "I"
+      #define FMTPD      "I"
+      #define FMTH       "I"
+   #endif
+#elif defined __APPLE__
+   /* Mac OS hosts use the same formatters for 32- and 64-bit. */
+   #define FMT64 "ll"
+   #if KERNEL
+      #define FMTSZ "l"
+   #else
+      #define FMTSZ "z"
+   #endif
+   #define FMTPD "l"
+   #define FMTH ""
+#elif __GNUC__
+   #define FMTH ""
+   #if defined(N_PLAT_NLM) || defined(sun) || \
+       (defined(__DragonFly__) && (__DragonFly__ + 0) && ((__DragonFly__ + 0) < 5))
+      /*
+       * Why (__DragonFly__ + 0)?  See bug 141008.
+       * Yes, we really need to test both (__DragonFly__ + 0) and
+       * ((__DragonFly__ + 0) < 5).  No, we can't remove "+ 0" from
+       * ((__DragonFly__ + 0) < 5).
+       */
+      #ifdef VM_X86_64
+         #define FMTSZ  "l"
+         #define FMTPD  "l"
+      #else
+         #define FMTSZ  ""
+         #define FMTPD  ""
+      #endif
+   #elif defined(__linux__) \
+      || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
+      || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \
+      || (defined(_POSIX2_VERSION) && _POSIX2_VERSION >= 200112L)
+      /* BSD, Linux */
+      #define FMTSZ     "z"
+
+      #if defined(VM_X86_64)
+         #define FMTPD  "l"
+      #else
+         #define FMTPD  ""
+      #endif
+   #else
+      /* Systems with a pre-C99 libc */
+      #define FMTSZ     "Z"
+      #ifdef VM_X86_64
+         #define FMTPD  "l"
+      #else
+         #define FMTPD  ""
+      #endif
+   #endif
+   #ifdef VM_X86_64
+      #define FMT64     "l"
+   #elif defined(sun) || defined(__DragonFly__)
+      #define FMT64     "ll"
+   #else
+      #define FMT64     "L"
+   #endif
+#else
+   #error - Need compiler define for FMT64 and FMTSZ
+#endif
+
+/*
+ * Suffix for 64-bit constants.  Use it like this:
+ *    CONST64(0x7fffffffffffffff) for signed or
+ *    CONST64U(0x7fffffffffffffff) for unsigned.
+ *
+ * 2004.08.30(thutt):
+ *   The vmcore/asm64/gen* programs are compiled as 32-bit
+ *   applications, but must handle 64 bit constants.  If the
+ *   64-bit-constant defining macros are already defined, the
+ *   definition will not be overwritten.
+ */
+
+#if !defined(CONST64) || !defined(CONST64U)
+#ifdef _MSC_VER
+#define CONST64(c) c##I64
+#define CONST64U(c) c##uI64
+#elif defined __APPLE__
+#define CONST64(c) c##LL
+#define CONST64U(c) c##uLL
+#elif __GNUC__
+#ifdef VM_X86_64
+#define CONST64(c) c##L
+#define CONST64U(c) c##uL
+#else
+#define CONST64(c) c##LL
+#define CONST64U(c) c##uLL
+#endif
+#else
+#error - Need compiler define for CONST64
+#endif
+#endif
+
+/*
+ * Use CONST3264/CONST3264U if you want a constant to be
+ * treated as a 32-bit number on 32-bit compiles and
+ * a 64-bit number on 64-bit compiles. Useful in the case
+ * of shifts, like (CONST3264U(1) << x), where x could be
+ * more than 31 on a 64-bit compile.
+ */
+
+#ifdef VM_X86_64
+    #define CONST3264(a) CONST64(a)
+    #define CONST3264U(a) CONST64U(a)
+#else
+    #define CONST3264(a) (a)
+    #define CONST3264U(a) (a)
+#endif
+
+#define MIN_INT8   ((int8)0x80)
+#define MAX_INT8   ((int8)0x7f)
+
+#define MIN_UINT8  ((uint8)0)
+#define MAX_UINT8  ((uint8)0xff)
+
+#define MIN_INT16  ((int16)0x8000)
+#define MAX_INT16  ((int16)0x7fff)
+
+#define MIN_UINT16 ((uint16)0)
+#define MAX_UINT16 ((uint16)0xffff)
+
+#define MIN_INT32  ((int32)0x80000000)
+#define MAX_INT32  ((int32)0x7fffffff)
+
+#define MIN_UINT32 ((uint32)0)
+#define MAX_UINT32 ((uint32)0xffffffff)
+
+#define MIN_INT64  (CONST64(0x8000000000000000))
+#define MAX_INT64  (CONST64(0x7fffffffffffffff))
+
+#define MIN_UINT64 (CONST64U(0))
+#define MAX_UINT64 (CONST64U(0xffffffffffffffff))
+
+typedef uint8 *TCA;  /* Pointer into TC (usually). */
+
+/*
+ * Type big enough to hold an integer between 0..100
+ */
+typedef uint8 Percent;
+#define AsPercent(v)	((Percent)(v))
+#define CHOOSE_PERCENT  AsPercent(101)
+
+
+typedef uintptr_t VA;
+typedef uintptr_t VPN;
+
+typedef uint64    PA;
+typedef uint32    PPN;
+
+typedef uint64    PhysMemOff;
+typedef uint64    PhysMemSize;
+
+/* The Xserver source compiles with -ansi -pendantic */
+#ifndef __STRICT_ANSI__
+typedef uint64    BA;
+#endif
+typedef uint32    BPN;
+typedef uint32    PageNum;
+typedef unsigned  MemHandle;
+typedef int32     World_ID;
+
+/* !! do not alter the definition of INVALID_WORLD_ID without ensuring
+ * that the values defined in both bora/public/vm_basic_types.h and
+ * lib/vprobe/vm_basic_types.h are the same.  Additionally, the definition
+ * of VMK_INVALID_WORLD_ID in vmkapi_world.h also must be defined with
+ * the same value
+ */
+
+#define INVALID_WORLD_ID ((World_ID)0)
+
+typedef World_ID User_CartelID;
+#define INVALID_CARTEL_ID INVALID_WORLD_ID
+
+typedef User_CartelID User_SessionID;
+#define INVALID_SESSION_ID INVALID_CARTEL_ID
+
+typedef User_CartelID User_CartelGroupID;
+#define INVALID_CARTELGROUP_ID INVALID_CARTEL_ID
+
+typedef uint32 Worldlet_ID;
+#define INVALID_WORLDLET_ID ((Worldlet_ID)-1)
+
+/* The Xserver source compiles with -ansi -pendantic */
+#ifndef __STRICT_ANSI__
+typedef uint64 MA;
+typedef uint32 MPN;
+#endif
+
+/*
+ * This type should be used for variables that contain sector
+ * position/quantity.
+ */
+typedef uint64 SectorType;
+
+/*
+ * Linear address
+ */
+
+typedef uintptr_t LA;
+typedef uintptr_t LPN;
+#define LA_2_LPN(_la)     ((_la) >> PAGE_SHIFT)
+#define LPN_2_LA(_lpn)    ((_lpn) << PAGE_SHIFT)
+
+#define LAST_LPN   ((((LA)  1) << (8 * sizeof(LA)   - PAGE_SHIFT)) - 1)
+#define LAST_LPN32 ((((LA32)1) << (8 * sizeof(LA32) - PAGE_SHIFT)) - 1)
+#define LAST_LPN64 ((((LA64)1) << (8 * sizeof(LA64) - PAGE_SHIFT)) - 1)
+
+/* Valid bits in a LPN. */
+#define LPN_MASK   LAST_LPN
+#define LPN_MASK32 LAST_LPN32
+#define LPN_MASK64 LAST_LPN64
+
+/*
+ * On 64 bit platform, address and page number types default
+ * to 64 bit. When we need to represent a 32 bit address, we use
+ * types defined below.
+ *
+ * On 32 bit platform, the following types are the same as the
+ * default types.
+ */
+typedef uint32 VA32;
+typedef uint32 VPN32;
+typedef uint32 LA32;
+typedef uint32 LPN32;
+typedef uint32 PA32;
+typedef uint32 PPN32;
+typedef uint32 MA32;
+typedef uint32 MPN32;
+
+/*
+ * On 64 bit platform, the following types are the same as the
+ * default types.
+ */
+typedef uint64 VA64;
+typedef uint64 VPN64;
+typedef uint64 LA64;
+typedef uint64 LPN64;
+typedef uint64 PA64;
+typedef uint64 PPN64;
+typedef uint64 MA64;
+typedef uint64 MPN64;
+
+/*
+ * VA typedefs for user world apps.
+ */
+typedef VA32 UserVA32;
+typedef VA64 UserVA64;
+typedef UserVA64 UserVAConst; /* Userspace ptr to data that we may only read. */
+typedef UserVA32 UserVA32Const; /* Userspace ptr to data that we may only read. */
+typedef UserVA64 UserVA64Const; /* Used by 64-bit syscalls until conversion is finished. */
+#ifdef VMKERNEL
+typedef UserVA64 UserVA;
+#else
+typedef void * UserVA;
+#endif
+
+
+/*
+ * Maximal possible PPN value (errors too) that PhysMem can handle.
+ * Must be at least as large as MAX_PPN which is the maximum PPN
+ * for any region other than buserror.
+ */
+#define PHYSMEM_MAX_PPN   ((PPN)0xffffffff)
+#define MAX_PPN           ((PPN)0x1fffffff) /* Maximal observable PPN value. */
+#define INVALID_PPN       ((PPN)0xffffffff)
+#define APIC_DISABLED_PPN ((PPN)0xfffffffe)
+
+#define INVALID_BPN       ((BPN)0x1fffffff)
+
+#define RESERVED_MPN      ((MPN) 0)
+#define INVALID_MPN       ((MPN)-1)
+#define MEMREF_MPN        ((MPN)-2)
+#define RELEASED_MPN      ((MPN)-3)
+#define MAX_MPN           ((MPN)0x7fffffff)  /* 43 bits of address space. */
+
+#define INVALID_LPN       ((LPN)-1)
+#define INVALID_VPN       ((VPN)-1)
+#define INVALID_LPN64     ((LPN64)-1)
+#define INVALID_PAGENUM   ((PageNum)-1)
+
+
+/*
+ * Format modifier for printing VA, LA, and VPN.
+ * Use them like this: Log("%#"FMTLA"x\n", laddr)
+ */
+
+#if defined(VMM) || defined(FROBOS64) || vm_x86_64 || defined __APPLE__
+#   define FMTLA "l"
+#   define FMTVA "l"
+#   define FMTVPN "l"
+#else
+#   define FMTLA ""
+#   define FMTVA ""
+#   define FMTVPN ""
+#endif
+
+#ifndef EXTERN
+#define EXTERN        extern
+#endif
+#define CONST         const
+
+
+#ifndef INLINE
+#   ifdef _MSC_VER
+#      define INLINE        __inline
+#   else
+#      define INLINE        inline
+#   endif
+#endif
+
+
+/*
+ * Annotation for data that may be exported into a DLL and used by other
+ * apps that load that DLL and import the data.
+ */
+#if defined(_WIN32) && defined(VMX86_IMPORT_DLLDATA)
+#  define VMX86_EXTERN_DATA       extern __declspec(dllimport)
+#else // !_WIN32
+#  define VMX86_EXTERN_DATA       extern
+#endif
+
+#if defined(_WIN32) && !defined(VMX86_NO_THREADS)
+#define THREADSPECIFIC __declspec(thread)
+#else
+#define THREADSPECIFIC
+#endif
+
+/*
+ * Due to the wonderful "registry redirection" feature introduced in
+ * 64-bit Windows, if you access any key under HKLM\Software in 64-bit
+ * code, you need to open/create/delete that key with
+ * VMKEY_WOW64_32KEY if you want a consistent view with 32-bit code.
+ */
+
+#ifdef _WIN32
+#ifdef _WIN64
+#define VMW_KEY_WOW64_32KEY KEY_WOW64_32KEY
+#else
+#define VMW_KEY_WOW64_32KEY 0x0
+#endif
+#endif
+
+
+/*
+ * At present, we effectively require a compiler that is at least
+ * gcc-3.3 (circa 2003).  Enforce this here, various things below
+ * this line depend upon it.
+ *
+ * In practice, most things presently compile with gcc-4.1 or gcc-4.4.
+ * The various linux kernel modules may use older (gcc-3.3) compilers.
+ */
+#if defined __GNUC__ && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3))
+#error "gcc version is to old to compile assembly, need gcc-3.3 or better"
+#endif
+
+
+/*
+ * Consider the following reasons functions are inlined:
+ *
+ *  1) inlined for performance reasons
+ *  2) inlined because it's a single-use function
+ *
+ * Functions which meet only condition 2 should be marked with this
+ * inline macro; It is not critical to be inlined (but there is a
+ * code-space & runtime savings by doing so), so when other callers
+ * are added the inline-ness should be removed.
+ */
+
+#if defined __GNUC__
+/*
+ * Starting at version 3.3, gcc does not always inline functions marked
+ * 'inline' (it depends on their size and other factors). To force gcc
+ * to inline a function, one must use the __always_inline__ attribute.
+ * This attribute should be used sparingly and with care.  It is usually
+ * preferable to let gcc make its own inlining decisions
+ */
+#   define INLINE_ALWAYS INLINE __attribute__((__always_inline__))
+#else
+#   define INLINE_ALWAYS INLINE
+#endif
+#define INLINE_SINGLE_CALLER INLINE_ALWAYS
+
+/*
+ * Used when a hard guaranteed of no inlining is needed. Very few
+ * instances need this since the absence of INLINE is a good hint
+ * that gcc will not do inlining.
+ */
+
+#if defined(__GNUC__) && defined(VMM)
+#define ABSOLUTELY_NOINLINE __attribute__((__noinline__))
+#endif
+
+/*
+ * Attributes placed on function declarations to tell the compiler
+ * that the function never returns.
+ */
+
+#ifdef _MSC_VER
+#define NORETURN __declspec(noreturn)
+#elif defined __GNUC__
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#endif
+
+/*
+ * Branch prediction hints:
+ *     LIKELY(exp)   - Expression exp is likely TRUE.
+ *     UNLIKELY(exp) - Expression exp is likely FALSE.
+ *   Usage example:
+ *        if (LIKELY(excCode == EXC_NONE)) {
+ *               or
+ *        if (UNLIKELY(REAL_MODE(vc))) {
+ *
+ * We know how to predict branches on gcc3 and later (hopefully),
+ * all others we don't so we do nothing.
+ */
+
+#if defined __GNUC__
+/*
+ * gcc3 uses __builtin_expect() to inform the compiler of an expected value.
+ * We use this to inform the static branch predictor. The '!!' in LIKELY
+ * will convert any !=0 to a 1.
+ */
+#define LIKELY(_exp)     __builtin_expect(!!(_exp), 1)
+#define UNLIKELY(_exp)   __builtin_expect((_exp), 0)
+#else
+#define LIKELY(_exp)      (_exp)
+#define UNLIKELY(_exp)    (_exp)
+#endif
+
+/*
+ * GCC's argument checking for printf-like functions
+ * This is conditional until we have replaced all `"%x", void *'
+ * with `"0x%08x", (uint32) void *'. Note that %p prints different things
+ * on different platforms.  Argument checking is enabled for the
+ * vmkernel, which has already been cleansed.
+ *
+ * fmtPos is the position of the format string argument, beginning at 1
+ * varPos is the position of the variable argument, beginning at 1
+ */
+
+#if defined(__GNUC__)
+# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos)))
+#else
+# define PRINTF_DECL(fmtPos, varPos)
+#endif
+
+#if defined(__GNUC__)
+# define SCANF_DECL(fmtPos, varPos) __attribute__((__format__(__scanf__, fmtPos, varPos)))
+#else
+# define SCANF_DECL(fmtPos, varPos)
+#endif
+
+/*
+ * UNUSED_PARAM should surround the parameter name and type declaration,
+ * e.g. "int MyFunction(int var1, UNUSED_PARAM(int var2))"
+ *
+ */
+
+#ifndef UNUSED_PARAM
+# if defined(__GNUC__)
+#  define UNUSED_PARAM(_parm) _parm  __attribute__((__unused__))
+# else
+#  define UNUSED_PARAM(_parm) _parm
+# endif
+#endif
+
+/*
+ * REGPARM defaults to REGPARM3; i.e., a request that gcc
+ * put the first three arguments in registers.  (It is fine
+ * if the function has fewer than three arguments.)  Gcc only.
+ * Syntactically, put REGPARM where you'd put INLINE or NORETURN.
+ *
+ * Note that 64-bit code already puts the first six arguments in
+ * registers, so these attributes are only useful for 32-bit code.
+ */
+
+#if defined(__GNUC__)
+# define REGPARM0 __attribute__((regparm(0)))
+# define REGPARM1 __attribute__((regparm(1)))
+# define REGPARM2 __attribute__((regparm(2)))
+# define REGPARM3 __attribute__((regparm(3)))
+# define REGPARM REGPARM3
+#else
+# define REGPARM0
+# define REGPARM1
+# define REGPARM2
+# define REGPARM3
+# define REGPARM
+#endif
+
+/*
+ * ALIGNED specifies minimum alignment in "n" bytes.
+ */
+
+#ifdef __GNUC__
+#define ALIGNED(n) __attribute__((__aligned__(n)))
+#else
+#define ALIGNED(n)
+#endif
+
+/*
+ * Once upon a time, this was used to silence compiler warnings that
+ * get generated when the compiler thinks that a function returns
+ * when it is marked noreturn.  Don't do it.  Use NOT_REACHED().
+ */
+
+#define INFINITE_LOOP()           do { } while (1)
+
+/*
+ * On FreeBSD (for the tools build), size_t is typedef'd if _BSD_SIZE_T_
+ * is defined. Use the same logic here so we don't define it twice. [greg]
+ */
+#ifdef __DragonFly__
+#   ifdef _BSD_SIZE_T_
+#      undef _BSD_SIZE_T_
+#      ifdef VM_I386
+#         ifdef VM_X86_64
+             typedef uint64 size_t;
+#         else
+             typedef uint32 size_t;
+#         endif
+#      endif /* VM_I386 */
+#   endif
+
+#   ifdef _BSD_SSIZE_T_
+#      undef _BSD_SSIZE_T_
+#      ifdef VM_I386
+#         ifdef VM_X86_64
+             typedef int64 ssize_t;
+#         else
+             typedef int32 ssize_t;
+#         endif
+#      endif /* VM_I386 */
+#   endif
+
+#else
+#   ifndef _SIZE_T
+#      ifdef VM_I386
+#         define _SIZE_T
+#         ifdef VM_X86_64
+             typedef uint64 size_t;
+#         else
+             typedef uint32 size_t;
+#         endif
+#      elif defined(__arm__)
+#         define _SIZE_T
+          typedef uint32 size_t;
+#      endif
+#   endif
+
+#   if !defined(FROBOS) && !defined(_SSIZE_T) && !defined(_SSIZE_T_) && \
+       !defined(ssize_t) && !defined(__ssize_t_defined) && \
+       !defined(_SSIZE_T_DECLARED) && !defined(_SSIZE_T_DEFINED_)
+#      ifdef VM_I386
+#         define _SSIZE_T
+#         define __ssize_t_defined
+#         define _SSIZE_T_DECLARED
+#         ifdef VM_X86_64
+             typedef int64 ssize_t;
+#         else
+             typedef int32 ssize_t;
+#         endif
+#      elif defined(__arm__)
+#         define _SSIZE_T
+#         define __ssize_t_defined
+#         define _SSIZE_T_DECLARED
+             typedef int32 ssize_t;
+#      endif
+#   endif
+
+#endif
+
+/*
+ * Format modifier for printing pid_t.  On sun the pid_t is a ulong, but on
+ * Linux it's an int.
+ * Use this like this: printf("The pid is %"FMTPID".\n", pid);
+ */
+#ifdef sun
+#   ifdef VM_X86_64
+#      define FMTPID "d"
+#   else
+#      define FMTPID "lu"
+#   endif
+#else
+# define FMTPID "d"
+#endif
+
+/*
+ * Format modifier for printing uid_t.  On Solaris 10 and earlier, uid_t
+ * is a ulong, but on other platforms it's an unsigned int.
+ * Use this like this: printf("The uid is %"FMTUID".\n", uid);
+ */
+#if defined(sun) && !defined(SOL11)
+#   ifdef VM_X86_64
+#      define FMTUID "u"
+#   else
+#      define FMTUID "lu"
+#   endif
+#else
+# define FMTUID "u"
+#endif
+
+/*
+ * Format modifier for printing mode_t.  On sun the mode_t is a ulong, but on
+ * Linux it's an int.
+ * Use this like this: printf("The mode is %"FMTMODE".\n", mode);
+ */
+#ifdef sun
+#   ifdef VM_X86_64
+#      define FMTMODE "o"
+#   else
+#      define FMTMODE "lo"
+#   endif
+#else
+# define FMTMODE "o"
+#endif
+
+/*
+ * Format modifier for printing time_t. Most platforms define a time_t to be
+ * a long int, but on FreeBSD (as of 5.0, it seems), the time_t is a signed
+ * size quantity. Refer to the definition of FMTSZ to see why we need silly
+ * preprocessor arithmetic.
+ * Use this like this: printf("The mode is %"FMTTIME".\n", time);
+ */
+#if defined(__DragonFly__) && (__DragonFly__ + 0) && ((__DragonFly__ + 0) >= 5)
+#   define FMTTIME FMTSZ"d"
+#else
+#   if defined(_MSC_VER)
+#      ifndef _SAFETIME_H_
+#         if (_MSC_VER < 1400) || defined(_USE_32BIT_TIME_T)
+#             define FMTTIME "ld"
+#         else
+#             define FMTTIME FMT64"d"
+#         endif
+#      else
+#         ifndef FMTTIME
+#            error "safetime.h did not define FMTTIME"
+#         endif
+#      endif
+#   else
+#      define FMTTIME "ld"
+#   endif
+#endif
+
+#ifdef __APPLE__
+/*
+ * Format specifier for all these annoying types such as {S,U}Int32
+ * which are 'long' in 32-bit builds
+ *       and  'int' in 64-bit builds.
+ */
+#   ifdef __LP64__
+#      define FMTLI ""
+#   else
+#      define FMTLI "l"
+#   endif
+
+/*
+ * Format specifier for all these annoying types such as NS[U]Integer
+ * which are  'int' in 32-bit builds
+ *       and 'long' in 64-bit builds.
+ */
+#   ifdef __LP64__
+#      define FMTIL "l"
+#   else
+#      define FMTIL ""
+#   endif
+#endif
+
+
+/*
+ * Define MXSemaHandle here so both vmmon and vmx see this definition.
+ */
+
+#ifdef _WIN32
+typedef uintptr_t MXSemaHandle;
+#else
+typedef int MXSemaHandle;
+#endif
+
+/*
+ * Define type for poll device handles.
+ */
+
+typedef int64 PollDevHandle;
+
+/*
+ * Define the utf16_t type.
+ */
+
+#if defined(_WIN32) && defined(_NATIVE_WCHAR_T_DEFINED)
+typedef wchar_t utf16_t;
+#else
+typedef uint16 utf16_t;
+#endif
+
+/*
+ * Define for point and rectangle types.  Defined here so they
+ * can be used by other externally facing headers in bora/public.
+ */
+
+typedef struct VMPoint {
+   int x, y;
+} VMPoint;
+
+#if defined _WIN32 && defined USERLEVEL
+struct tagRECT;
+typedef struct tagRECT VMRect;
+#else
+typedef struct VMRect {
+   int left;
+   int top;
+   int right;
+   int bottom;
+} VMRect;
+#endif
+
+/*
+ * ranked locks "everywhere"
+ */
+
+typedef uint32 MX_Rank;
+
+#endif  /* _VM_BASIC_TYPES_H_ */
diff --git a/sys/dev/virtual/vmware/shared/vm_device_version.h b/sys/dev/virtual/vmware/shared/vm_device_version.h
new file mode 100644
index 0000000..4398bf7
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vm_device_version.h
@@ -0,0 +1,258 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef VM_DEVICE_VERSION_H
+#define VM_DEVICE_VERSION_H
+
+#define INCLUDE_ALLOW_USERLEVEL
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#ifdef _WIN32
+#ifdef __MINGW32__
+#include "initguid.h"
+#else
+#include "guiddef.h"
+#endif
+#endif
+
+/* LSILogic 53C1030 Parallel SCSI controller
+ * LSILogic SAS1068 SAS controller
+ */
+#define PCI_VENDOR_ID_LSILOGIC          0x1000
+#define PCI_DEVICE_ID_LSI53C1030        0x0030
+#define PCI_DEVICE_ID_LSISAS1068        0x0054
+
+/* Our own PCI IDs
+ *    VMware SVGA II (Unified VGA)
+ *    VMware SVGA (PCI Accelerator)
+ *    VMware vmxnet (Idealized NIC)
+ *    VMware vmxscsi (Abortive idealized SCSI controller)
+ *    VMware chipset (Subsystem ID for our motherboards)
+ *    VMware e1000 (Subsystem ID)
+ *    VMware vmxnet3 (Uniform Pass Through NIC)
+ *    VMware HD Audio codec
+ *    VMware HD Audio controller
+ */
+#define PCI_VENDOR_ID_VMWARE                    0x15AD
+#define PCI_DEVICE_ID_VMWARE_SVGA2              0x0405
+#define PCI_DEVICE_ID_VMWARE_SVGA               0x0710
+#define PCI_DEVICE_ID_VMWARE_NET                0x0720
+#define PCI_DEVICE_ID_VMWARE_SCSI               0x0730
+#define PCI_DEVICE_ID_VMWARE_VMCI               0x0740
+#define PCI_DEVICE_ID_VMWARE_CHIPSET            0x1976
+#define PCI_DEVICE_ID_VMWARE_82545EM            0x0750 /* single port */
+#define PCI_DEVICE_ID_VMWARE_82546EB            0x0760 /* dual port   */
+#define PCI_DEVICE_ID_VMWARE_EHCI               0x0770
+#define PCI_DEVICE_ID_VMWARE_UHCI               0x0774
+#define PCI_DEVICE_ID_VMWARE_XHCI               0x0778
+#define PCI_DEVICE_ID_VMWARE_1394               0x0780
+#define PCI_DEVICE_ID_VMWARE_BRIDGE             0x0790
+#define PCI_DEVICE_ID_VMWARE_ROOTPORT           0x07A0
+#define PCI_DEVICE_ID_VMWARE_VMXNET3            0x07B0
+#define PCI_DEVICE_ID_VMWARE_VMXWIFI            0x07B8
+#define PCI_DEVICE_ID_VMWARE_PVSCSI             0x07C0
+#define PCI_DEVICE_ID_VMWARE_82574              0x07D0
+#define PCI_DEVICE_ID_VMWARE_HDAUDIO_CODEC      0x1975
+#define PCI_DEVICE_ID_VMWARE_HDAUDIO_CONTROLLER 0x1977
+
+/* The hypervisor device might grow.  Please leave room
+ * for 7 more subfunctions.
+ */
+#define PCI_DEVICE_ID_VMWARE_HYPER      0x0800
+#define PCI_DEVICE_ID_VMWARE_VMI        0x0801
+
+#define PCI_DEVICE_VMI_CLASS            0x05
+#define PCI_DEVICE_VMI_SUBCLASS         0x80
+#define PCI_DEVICE_VMI_INTERFACE        0x00
+#define PCI_DEVICE_VMI_REVISION         0x01
+
+/* From linux/pci_ids.h:
+ *   AMD Lance Ethernet controller
+ *   BusLogic SCSI controller
+ *   Ensoniq ES1371 sound controller
+ */
+#define PCI_VENDOR_ID_AMD               0x1022
+#define PCI_DEVICE_ID_AMD_VLANCE        0x2000
+#define PCI_VENDOR_ID_BUSLOGIC			0x104B
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC	0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER	0x1040
+#define PCI_VENDOR_ID_ENSONIQ           0x1274
+#define PCI_DEVICE_ID_ENSONIQ_ES1371    0x1371
+
+/* From linux/pci_ids.h:
+ *    Intel 82439TX (430 HX North Bridge)
+ *    Intel 82371AB (PIIX4 South Bridge)
+ *    Intel 82443BX (440 BX North Bridge and AGP Bridge)
+ *    Intel 82545EM (e1000, server adapter, single port)
+ *    Intel 82546EB (e1000, server adapter, dual port)
+ *    Intel HECI (as embedded in ich9m)
+ */
+#define PCI_VENDOR_ID_INTEL             0x8086
+#define PCI_DEVICE_ID_INTEL_82439TX     0x7100
+#define PCI_DEVICE_ID_INTEL_82371AB_0   0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB_2   0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3   0x7113
+#define PCI_DEVICE_ID_INTEL_82371AB     0x7111
+#define PCI_DEVICE_ID_INTEL_82443BX     0x7190
+#define PCI_DEVICE_ID_INTEL_82443BX_1   0x7191
+#define PCI_DEVICE_ID_INTEL_82443BX_2   0x7192 /* Used when no AGP support */
+#define PCI_DEVICE_ID_INTEL_82545EM     0x100f
+#define PCI_DEVICE_ID_INTEL_82546EB     0x1010
+#define PCI_DEVICE_ID_INTEL_82574       0x10d3
+#define PCI_DEVICE_ID_INTEL_82574_APPLE 0x10f6
+#define PCI_DEVICE_ID_INTEL_HECI        0x2a74
+
+#define E1000E_PCI_DEVICE_ID_CONFIG_STR "e1000e.pci.deviceID"
+#define E1000E_PCI_SUB_VENDOR_ID_CONFIG_STR "e1000e.pci.subVendorID"
+#define E1000E_PCI_SUB_DEVICE_ID_CONFIG_STR "e1000e.pci.subDeviceID"
+
+/*
+ * Intel HD Audio controller and Realtek ALC885 codec.
+ */
+#define PCI_DEVICE_ID_INTEL_631XESB_632XESB  0x269a
+#define PCI_VENDOR_ID_REALTEK                0x10ec
+#define PCI_DEVICE_ID_REALTEK_ALC885         0x0885
+
+
+/*
+ * Fresco Logic xHCI (USB 3.0) Controller
+ */
+#define PCI_VENDOR_ID_FRESCO            0x1B73
+#define PCI_DEVICE_ID_FRESCO_FL1000     0x1000   // Original 1-port chip
+#define PCI_DEVICE_ID_FRESCO_FL1009     0x1009   // New 2-port chip (Driver 3.0.98+)
+#define PCI_DEVICE_ID_FRESCO_FL1400     0x1400   // Unknown (4-port? Dev hardware?)
+
+/*
+ * NEC/Renesas xHCI (USB 3.0) Controller
+ */
+#define PCI_VENDOR_ID_NEC               0x1033
+#define PCI_DEVICE_ID_NEC_UPD720200     0x0194
+#define PCI_REVISION_NEC_UPD720200      0x03
+#define PCI_FIRMWARE_NEC_UPD720200      0x3015
+
+
+/************* Strings for IDE Identity Fields **************************/
+#define VIDE_ID_SERIAL_STR	"00000000000000000001"	/* Must be 20 Bytes */
+#define VIDE_ID_FIRMWARE_STR	"00000001"		/* Must be 8 Bytes */
+
+/* No longer than 40 Bytes */
+#define VIDE_ATA_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE Hard Drive"
+#define VIDE_ATAPI_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE CDROM Drive"
+
+#define ATAPI_VENDOR_ID	"NECVMWar"		/* Must be 8 Bytes */
+#define ATAPI_PRODUCT_ID PRODUCT_GENERIC_NAME " IDE CDROM"	/* Must be 16 Bytes */
+#define ATAPI_REV_LEVEL	"1.00"			/* Must be 4 Bytes */
+
+#define IDE_NUM_INTERFACES   2	/* support for two interfaces */
+#define IDE_DRIVES_PER_IF    2
+
+/************* Strings for SCSI Identity Fields **************************/
+#define SCSI_DISK_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI Hard Drive"
+#define SCSI_DISK_VENDOR_NAME COMPANY_NAME
+#define SCSI_DISK_REV_LEVEL "1.0"
+#define SCSI_CDROM_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI CDROM Drive"
+#define SCSI_CDROM_VENDOR_NAME COMPANY_NAME
+#define SCSI_CDROM_REV_LEVEL "1.0"
+
+/************* SCSI implementation limits ********************************/
+#define SCSI_MAX_CONTROLLERS	 4	  // Need more than 1 for MSCS clustering
+#define	SCSI_MAX_DEVICES	 16	  // BT-958 emulates only 16
+#define PVSCSI_MAX_DEVICES       255      // 255 (including the controller)
+/*
+ * VSCSI_BV_INTS is the number of uint32's needed for a bit vector
+ * to cover all scsi devices per target.
+ */
+#define VSCSI_BV_INTS            CEILING(PVSCSI_MAX_DEVICES, 8 * sizeof (uint32))
+#define SCSI_IDE_CHANNEL         SCSI_MAX_CONTROLLERS
+#define SCSI_IDE_HOSTED_CHANNEL  (SCSI_MAX_CONTROLLERS + 1)
+#define SCSI_MAX_CHANNELS        (SCSI_MAX_CONTROLLERS + 2)
+
+/************* Strings for the VESA BIOS Identity Fields *****************/
+#define VBE_OEM_STRING COMPANY_NAME " SVGA"
+#define VBE_VENDOR_NAME COMPANY_NAME
+#define VBE_PRODUCT_NAME PRODUCT_GENERIC_NAME
+
+/************* PCI implementation limits ********************************/
+#define PCI_MAX_BRIDGES         15
+
+/************* Ethernet implementation limits ***************************/
+#define MAX_ETHERNET_CARDS      10
+
+/********************** Floppy limits ***********************************/
+#define MAX_FLOPPY_DRIVES      2
+
+/************* PCI Passthrough implementation limits ********************/
+#define MAX_PCI_PASSTHRU_DEVICES 6
+
+/************* USB implementation limits ********************************/
+#define MAX_USB_DEVICES_PER_HOST_CONTROLLER 127
+
+/************* Strings for Host USB Driver *******************************/
+
+#ifdef _WIN32
+
+/*
+ * Globally unique ID for the VMware device interface. Define INITGUID before including
+ * this header file to instantiate the variable.
+ */
+DEFINE_GUID(GUID_DEVICE_INTERFACE_VMWARE_USB_DEVICES,
+0x2da1fe75, 0xaab3, 0x4d2c, 0xac, 0xdf, 0x39, 0x8, 0x8c, 0xad, 0xa6, 0x65);
+
+/*
+ * Globally unique ID for the VMware device setup class.
+ */
+DEFINE_GUID(GUID_CLASS_VMWARE_USB_DEVICES,
+0x3b3e62a5, 0x3556, 0x4d7e, 0xad, 0xad, 0xf5, 0xfa, 0x3a, 0x71, 0x2b, 0x56);
+
+/*
+ * This string defines the device ID string of a VMware USB device.
+ * The format is USB\Vid_XXXX&Pid_YYYY, where XXXX and YYYY are the
+ * hexadecimal representations of the vendor and product ids, respectively.
+ *
+ * The official vendor ID for VMware, Inc. is 0x0E0F.
+ * The product id for USB generic devices is 0x0001.
+ */
+#define USB_VMWARE_DEVICE_ID_WIDE L"USB\\Vid_0E0F&Pid_0001"
+#define USB_DEVICE_ID_LENGTH (sizeof(USB_VMWARE_DEVICE_ID_WIDE) / sizeof(WCHAR))
+
+#ifdef UNICODE
+#define USB_PNP_SETUP_CLASS_NAME L"VMwareUSBDevices"
+#define USB_PNP_DRIVER_NAME L"vmusb"
+#else
+#define USB_PNP_SETUP_CLASS_NAME "VMwareUSBDevices"
+#define USB_PNP_DRIVER_NAME "vmusb"
+#endif
+#endif
+
+#endif /* VM_DEVICE_VERSION_H */
diff --git a/sys/dev/virtual/vmware/shared/vmware.h b/sys/dev/virtual/vmware/shared/vmware.h
new file mode 100644
index 0000000..90db513
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vmware.h
@@ -0,0 +1,69 @@
+/*********************************************************
+ * Copyright (C) 2003 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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_
diff --git a/sys/dev/virtual/vmware/shared/vmware_pack_begin.h b/sys/dev/virtual/vmware/shared/vmware_pack_begin.h
new file mode 100644
index 0000000..ad3db30
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vmware_pack_begin.h
@@ -0,0 +1,55 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
diff --git a/sys/dev/virtual/vmware/shared/vmware_pack_end.h b/sys/dev/virtual/vmware/shared/vmware_pack_end.h
new file mode 100644
index 0000000..6e55e1c
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vmware_pack_end.h
@@ -0,0 +1,56 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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
diff --git a/sys/dev/virtual/vmware/shared/vmware_pack_init.h b/sys/dev/virtual/vmware/shared/vmware_pack_init.h
new file mode 100644
index 0000000..bee76b1
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/vmware_pack_init.h
@@ -0,0 +1,77 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#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__ */
diff --git a/sys/dev/virtual/vmware/shared/x86cpuid.h b/sys/dev/virtual/vmware/shared/x86cpuid.h
new file mode 100644
index 0000000..6f534e8
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/x86cpuid.h
@@ -0,0 +1,1165 @@
+/*********************************************************
+ * Copyright (C) 1998-2008 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#ifndef _X86CPUID_H_
+#define _X86CPUID_H_
+
+/* http://www.sandpile.org/ia32/cpuid.htm */
+
+#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"
+#include "x86vendor.h"
+
+/*
+ * The linux kernel's ptrace.h stupidly defines the bare
+ * EAX/EBX/ECX/EDX, which wrecks havoc with our preprocessor tricks.
+ */
+#undef EAX
+#undef EBX
+#undef ECX
+#undef EDX
+
+typedef struct CPUIDRegs {
+   uint32 eax, ebx, ecx, edx;
+} CPUIDRegs;
+
+typedef union CPUIDRegsUnion {
+   uint32 array[4];
+   CPUIDRegs regs;
+} CPUIDRegsUnion;
+
+/*
+ * Results of calling cpuid(eax, ecx) on all host logical CPU.
+ */
+#ifdef _MSC_VER
+#pragma warning (disable :4200) // non-std extension: zero-sized array in struct
+#endif
+
+typedef
+#include "vmware_pack_begin.h"
+struct CPUIDReply {
+   /*
+    * 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
+
+   CPUIDRegs regs;            // OUT
+}
+#include "vmware_pack_end.h"
+CPUIDReply;
+
+typedef
+#include "vmware_pack_begin.h"
+struct CPUIDQuery {
+   uint32 eax;                // IN
+   uint32 ecx;                // IN
+   uint32 numLogicalCPUs;     // IN/OUT
+   CPUIDReply logicalCPUs[0]; // OUT
+}
+#include "vmware_pack_end.h"
+CPUIDQuery;
+
+/*
+ * CPUID levels the monitor caches and ones that are not cached, but
+ * have fields defined below (short name and actual value).
+ *
+ * The first parameter defines whether the level has its default masks
+ * generated from the values in this file.  Any level which is marked
+ * as FALSE here *must* have all monitor support types set to NA.  A
+ * static assert in lib/cpuidcompat/cpuidcompat.c will check this.
+ */
+
+#define CPUID_CACHED_LEVELS                     \
+   CPUIDLEVEL(TRUE,  0,  0)                     \
+   CPUIDLEVEL(TRUE,  1,  1)                     \
+   CPUIDLEVEL(FALSE, 5,  5)                     \
+   CPUIDLEVEL(TRUE,  7,  7)                     \
+   CPUIDLEVEL(TRUE,  D,  0xD)                   \
+   CPUIDLEVEL(FALSE,400, 0x40000000)            \
+   CPUIDLEVEL(FALSE,410, 0x40000010)            \
+   CPUIDLEVEL(FALSE, 80, 0x80000000)            \
+   CPUIDLEVEL(TRUE,  81, 0x80000001)            \
+   CPUIDLEVEL(FALSE, 87, 0x80000007)            \
+   CPUIDLEVEL(FALSE, 88, 0x80000008)            \
+   CPUIDLEVEL(TRUE,  8A, 0x8000000A)
+
+#define CPUID_UNCACHED_LEVELS                   \
+   CPUIDLEVEL(FALSE, 4, 4)                      \
+   CPUIDLEVEL(FALSE, 6, 6)                      \
+   CPUIDLEVEL(FALSE, A, 0xA)                    \
+   CPUIDLEVEL(FALSE, B, 0xB)                    \
+   CPUIDLEVEL(FALSE, 85, 0x80000005)            \
+   CPUIDLEVEL(FALSE, 86, 0x80000006)            \
+   CPUIDLEVEL(FALSE, 819, 0x80000019)           \
+   CPUIDLEVEL(FALSE, 81A, 0x8000001A)           \
+   CPUIDLEVEL(FALSE, 81B, 0x8000001B)           \
+   CPUIDLEVEL(FALSE, 81C, 0x8000001C)           \
+   CPUIDLEVEL(FALSE, 81D, 0x8000001D)           \
+   CPUIDLEVEL(FALSE, 81E, 0x8000001E)
+
+#define CPUID_ALL_LEVELS                        \
+   CPUID_CACHED_LEVELS                          \
+   CPUID_UNCACHED_LEVELS
+
+/* Define cached CPUID levels in the form: CPUID_LEVEL_<ShortName> */
+typedef enum {
+#define CPUIDLEVEL(t, s, v) CPUID_LEVEL_##s,
+   CPUID_CACHED_LEVELS
+#undef CPUIDLEVEL
+   CPUID_NUM_CACHED_LEVELS
+} CpuidCachedLevel;
+
+
+/* SVM CPUID feature leaf */
+#define CPUID_SVM_FEATURES         0x8000000a
+
+
+/*
+ * CPUID result registers
+ */
+
+#define CPUID_REGS                              \
+   CPUIDREG(EAX, eax)                           \
+   CPUIDREG(EBX, ebx)                           \
+   CPUIDREG(ECX, ecx)                           \
+   CPUIDREG(EDX, edx)
+
+typedef enum {
+#define CPUIDREG(uc, lc) CPUID_REG_##uc,
+   CPUID_REGS
+#undef CPUIDREG
+   CPUID_NUM_REGS
+} CpuidReg;
+
+#define CPUID_INTEL_VENDOR_STRING       "GenuntelineI"
+#define CPUID_AMD_VENDOR_STRING         "AuthcAMDenti"
+#define CPUID_CYRIX_VENDOR_STRING       "CyriteadxIns"
+#define CPUID_VIA_VENDOR_STRING         "CentaulsaurH"
+
+#define CPUID_HYPERV_HYPERVISOR_VENDOR_STRING  "Microsoft Hv"
+#define CPUID_KVM_HYPERVISOR_VENDOR_STRING     "KVMKVMKVM\0\0\0"
+#define CPUID_VMWARE_HYPERVISOR_VENDOR_STRING  "VMwareVMware"
+#define CPUID_XEN_HYPERVISOR_VENDOR_STRING     "XenVMMXenVMM"
+
+#define CPUID_INTEL_VENDOR_STRING_FIXED "GenuineIntel"
+#define CPUID_AMD_VENDOR_STRING_FIXED   "AuthenticAMD"
+#define CPUID_CYRIX_VENDOR_STRING_FIXED "CyrixInstead"
+#define CPUID_VIA_VENDOR_STRING_FIXED   "CentaurHauls"
+
+/*
+ * FIELDDEF can be defined to process the CPUID information provided
+ * in the following CPUID_FIELD_DATA macro.  The first parameter is
+ * the CPUID level of the feature (must be defined in
+ * CPUID_ALL_LEVELS, above.  The second parameter is the CPUID result
+ * register in which the field is returned (defined in CPUID_REGS).
+ * The third field is the vendor(s) this feature applies to.  "COMMON"
+ * means all vendors apply.  UNKNOWN may not be used here.  The fourth
+ * and fifth parameters are the bit position of the field and the
+ * width, respectively.  The sixth is the text name of the field.
+ *
+ * The seventh parameters specifies the monitor support
+ * characteristics for this field.  The value must be a valid
+ * CpuidFieldSupported value (omitting CPUID_FIELD_SUPPORT_ for
+ * convenience).  The meaning of those values are described below.
+ *
+ * The eighth parameter describes whether the feature is capable of
+ * being used by usermode code (TRUE), or just CPL0 kernel code
+ * (FALSE).
+ *
+ * FIELDDEFA takes a ninth parameter: the name used when generating
+ * accessor functions in lib/public/cpuidInfoFuncs.h.
+ *
+ * FLAGDEF/FLAGDEFA is defined identically to fields, but their
+ * accessors are more appropriate for 1-bit flags, and compile-time
+ * asserts enforce that the size is 1 bit wide.
+ */
+
+
+/*
+ * CpuidFieldSupported is made up of the following values:
+ *
+ *     NO: A feature/field that IS NOT SUPPORTED by the monitor.  Even
+ *     if the host supports this feature, we will never expose it to
+ *     the guest.
+ *
+ *     YES: A feature/field that IS SUPPORTED by the monitor.  If the
+ *     host supports this feature, we will expose it to the guest.  If
+ *     not, then we will not set the feature.
+ *
+ *     ANY: A feature/field that IS ALWAYS SUPPORTED by the monitor.
+ *     Even if the host does not support the feature, the monitor can
+ *     expose the feature to the guest.
+ *
+ *     NA: Only legal for levels not masked/tested by default (see
+ *     above for this definition).  Such fields must always be marked
+ *     as NA.
+ *
+ * These distinctions, when combined with the feature's CPL3
+ * properties can be translated into a common CPUID mask string as
+ * follows:
+ *
+ *     NO + CPL3 --> "R" (Reserved).  We don't support the feature,
+ *     but we can't properly hide this from applications when using
+ *     direct execution or HV with apps that do try/catch/fail, so we
+ *     must still perform compatibility checks.
+ *
+ *     NO + !CPL3 --> "0" (Masked).  We can hide this from the guest.
+ *
+ *     YES --> "H" (Host).  We support the feature, so show it to the
+ *     guest if the host has the feature.
+ *
+ *     ANY/NA --> "X" (Ignore).  By default, don't perform checks for
+ *     this feature bit.  Per-GOS masks may choose to set this bit in
+ *     the guest.  (e.g. the APIC feature bit is always set to 1.)
+ *
+ *     See lib/cpuidcompat/cpuidcompat.c for any possible overrides to
+ *     these defaults.
+ */
+typedef enum {
+   CPUID_FIELD_SUPPORTED_NO,
+   CPUID_FIELD_SUPPORTED_YES,
+   CPUID_FIELD_SUPPORTED_ANY,
+   CPUID_FIELD_SUPPORTED_NA,
+   CPUID_NUM_FIELD_SUPPORTEDS
+} CpuidFieldSupported;
+
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_0                                               \
+FIELDDEF(  0, EAX, COMMON,  0, 32, NUMLEVELS,           ANY, FALSE)     \
+FIELDDEF(  0, EBX, COMMON,  0, 32, VENDOR1,             YES, TRUE)      \
+FIELDDEF(  0, ECX, COMMON,  0, 32, VENDOR3,             YES, TRUE)      \
+FIELDDEF(  0, EDX, COMMON,  0, 32, VENDOR2,             YES, TRUE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_1                                               \
+FIELDDEFA( 1, EAX, COMMON,  0,  4, STEPPING,            ANY, FALSE, STEPPING)  \
+FIELDDEFA( 1, EAX, COMMON,  4,  4, MODEL,               ANY, FALSE, MODEL)     \
+FIELDDEFA( 1, EAX, COMMON,  8,  4, FAMILY,              YES, FALSE, FAMILY)    \
+FIELDDEF(  1, EAX, COMMON, 12,  2, TYPE,                ANY, FALSE)            \
+FIELDDEFA( 1, EAX, COMMON, 16,  4, EXTMODEL,            ANY, FALSE, EXT_MODEL) \
+FIELDDEFA( 1, EAX, COMMON, 20,  8, EXTFAMILY,           YES, FALSE, EXT_FAMILY) \
+FIELDDEF(  1, EBX, COMMON,  0,  8, BRAND_ID,            ANY, FALSE)            \
+FIELDDEF(  1, EBX, COMMON,  8,  8, CLFL_SIZE,           ANY, FALSE)            \
+FIELDDEFA( 1, EBX, COMMON, 16,  8, LCPU_COUNT,          ANY, FALSE, LCPU_COUNT) \
+FIELDDEFA( 1, EBX, COMMON, 24,  8, APICID,              ANY, FALSE, APICID)    \
+FLAGDEFA(  1, ECX, COMMON, 0,   1, SSE3,                YES, TRUE,  SSE3)      \
+FLAGDEFA(  1, ECX, COMMON, 1,   1, PCLMULQDQ,           YES, TRUE, PCLMULQDQ)  \
+FLAGDEF(   1, ECX, INTEL,  2,   1, NDA2,                NO,  FALSE)            \
+FLAGDEFA(  1, ECX, COMMON, 3,   1, MWAIT,               ANY, FALSE, MWAIT)     \
+FLAGDEFA(  1, ECX, INTEL,  4,   1, DSCPL,               NO,  FALSE, DSCPL)     \
+FLAGDEFA(  1, ECX, INTEL,  5,   1, VMX,                 YES, FALSE, VMX)       \
+FLAGDEF(   1, ECX, VIA,    5,   1, VMX,                 YES, FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  6,   1, SMX,                 NO,  FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  7,   1, EST,                 NO,  FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  8,   1, TM2,                 NO,  FALSE)            \
+FLAGDEFA(  1, ECX, COMMON, 9,   1, SSSE3,               YES, TRUE,  SSSE3)     \
+FLAGDEF(   1, ECX, INTEL,  10,  1, HTCACHE,             NO,  FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  11,  1, NDA11,               NO,  FALSE)            \
+FLAGDEFA(  1, ECX, COMMON, 12,  1, FMA,                 YES, TRUE,  FMA)       \
+FLAGDEFA(  1, ECX, COMMON, 13,  1, CMPX16,              YES, TRUE,  CMPX16)    \
+FLAGDEF(   1, ECX, INTEL,  14,  1, xPPR,                NO,  FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  15,  1, PERF_MSR,            NO,  FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  17,  1, PCID,                NO,  FALSE)            \
+FLAGDEF(   1, ECX, INTEL,  18,  1, DCA,                 NO,  FALSE)            \
+FLAGDEFA(  1, ECX, COMMON, 19,  1, SSE41,               YES, TRUE,  SSE41)     \
+FLAGDEFA(  1, ECX, COMMON, 20,  1, SSE42,               YES, TRUE,  SSE42)     \
+FLAGDEF(   1, ECX, INTEL,  21,  1, X2APIC,              NO,  FALSE)            \
+FLAGDEFA(  1, ECX, INTEL,  22,  1, MOVBE,               YES, TRUE,  MOVBE)     \
+FLAGDEFA(  1, ECX, COMMON, 23,  1, POPCNT,              YES, TRUE,  POPCNT)    \
+FLAGDEFA(  1, ECX, COMMON, 25,  1, AES,                 YES, TRUE, AES)        \
+FLAGDEFA(  1, ECX, COMMON, 26,  1, XSAVE,               YES, FALSE, XSAVE)     \
+FLAGDEFA(  1, ECX, COMMON, 27,  1, OSXSAVE,             ANY, FALSE, OSXSAVE)   \
+FLAGDEFA(  1, ECX, COMMON, 28,  1, AVX,                 YES, FALSE, AVX)       \
+FLAGDEFA(  1, ECX, COMMON, 29,  1, F16,                 YES, TRUE,  F16)       \
+FLAGDEFA(  1, ECX, COMMON, 30,  1, RDRAND,              YES, TRUE,  RDRAND)    \
+FLAGDEFA(  1, ECX, COMMON, 31,  1, HYPERVISOR,          ANY, FALSE, HYPERVISOR)\
+FLAGDEFA(  1, EDX, COMMON, 0,   1, FPU,                 YES, TRUE, FPU)        \
+FLAGDEFA(  1, EDX, COMMON, 1,   1, VME,                 YES, FALSE, VME)       \
+FLAGDEF(   1, EDX, COMMON, 2,   1, DBGE,                YES, FALSE)            \
+FLAGDEF(   1, EDX, COMMON, 3,   1, PGSZE,               YES, FALSE)            \
+FLAGDEFA(  1, EDX, COMMON, 4,   1, TSC,                 YES, TRUE, TSC)        \
+FLAGDEF(   1, EDX, COMMON, 5,   1, MSR,                 YES, FALSE)            \
+FLAGDEFA(  1, EDX, COMMON, 6,   1, PAE,                 YES, FALSE, PAE)       \
+FLAGDEF(   1, EDX, COMMON, 7,   1, MCK,                 YES, FALSE)            \
+FLAGDEF(   1, EDX, COMMON, 8,   1, CPMX,                YES, TRUE)             \
+FLAGDEFA(  1, EDX, COMMON, 9,   1, APIC,                ANY, FALSE, APIC)      \
+FLAGDEFA(  1, EDX, COMMON, 11,  1, SEP,                 YES, TRUE,  SEP)       \
+FLAGDEFA(  1, EDX, COMMON, 12,  1, MTRR,                YES, FALSE, MTRR)      \
+FLAGDEFA(  1, EDX, COMMON, 13,  1, PGE,                 YES, FALSE, PGE)       \
+FLAGDEFA(  1, EDX, COMMON, 14,  1, MCA,                 YES, FALSE, MCA)       \
+FLAGDEFA(  1, EDX, COMMON, 15,  1, CMOV,                YES, TRUE,  CMOV)      \
+FLAGDEFA(  1, EDX, COMMON, 16,  1, PAT,                 YES, FALSE, PAT)       \
+FLAGDEF(   1, EDX, COMMON, 17,  1, 36PG,                YES, FALSE)            \
+FLAGDEF(   1, EDX, INTEL,  18,  1, PSN,                 YES, FALSE)            \
+FLAGDEFA(  1, EDX, COMMON, 19,  1, CLFL,                YES, TRUE,  CLFL)      \
+FLAGDEF(   1, EDX, INTEL,  21,  1, DTES,                YES, FALSE)            \
+FLAGDEF(   1, EDX, INTEL,  22,  1, ACPI,                YES, FALSE)            \
+FLAGDEFA(  1, EDX, COMMON, 23,  1, MMX,                 YES, TRUE,  MMX)       \
+FLAGDEFA(  1, EDX, COMMON, 24,  1, FXSAVE,              YES, TRUE,  FXSAVE)    \
+FLAGDEFA(  1, EDX, COMMON, 25,  1, SSE,                 YES, TRUE,  SSE)       \
+FLAGDEFA(  1, EDX, COMMON, 26,  1, SSE2,                YES, TRUE,  SSE2)      \
+FLAGDEF(   1, EDX, INTEL,  27,  1, SS,                  YES, FALSE)            \
+FLAGDEFA(  1, EDX, COMMON, 28,  1, HT,                  ANY, FALSE, HT)        \
+FLAGDEF(   1, EDX, INTEL,  29,  1, TM,                  NO,  FALSE)            \
+FLAGDEF(   1, EDX, INTEL,  30,  1, IA64,                NO,  FALSE)            \
+FLAGDEF(   1, EDX, INTEL,  31,  1, PBE,                 NO,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_4                                               \
+FIELDDEF(  4, EAX, INTEL,   0,  5, CACHE_TYPE,          NA,  FALSE)            \
+FIELDDEF(  4, EAX, INTEL,   5,  3, CACHE_LEVEL,         NA,  FALSE)            \
+FLAGDEF(   4, EAX, INTEL,   8,  1, CACHE_SELF_INIT,     NA,  FALSE)            \
+FLAGDEF(   4, EAX, INTEL,   9,  1, CACHE_FULLY_ASSOC,   NA,  FALSE)            \
+FIELDDEF(  4, EAX, INTEL,  14, 12, CACHE_NUMHT_SHARING, NA,  FALSE)            \
+FIELDDEFA( 4, EAX, INTEL,  26,  6, CORE_COUNT,          NA,  FALSE, INTEL_CORE_COUNT)  \
+FIELDDEF(  4, EBX, INTEL,   0, 12, CACHE_LINE,          NA,  FALSE)            \
+FIELDDEF(  4, EBX, INTEL,  12, 10, CACHE_PART,          NA,  FALSE)            \
+FIELDDEF(  4, EBX, INTEL,  22, 10, CACHE_WAYS,          NA,  FALSE)            \
+FIELDDEF(  4, ECX, INTEL,   0, 32, CACHE_SETS,          NA,  FALSE)            \
+FLAGDEF(   4, EDX, INTEL,   0,  1, CACHE_WBINVD_NOT_GUARANTEED, NA,  FALSE)    \
+FLAGDEF(   4, EDX, INTEL,   1,  1, CACHE_IS_INCLUSIVE,  NA,  FALSE)
+
+/*     LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_5                                           \
+FIELDDEFA( 5, EAX, COMMON,  0, 16, MWAIT_MIN_SIZE,      NA,  FALSE, MWAIT_MIN_SIZE) \
+FIELDDEFA( 5, EBX, COMMON,  0, 16, MWAIT_MAX_SIZE,      NA,  FALSE, MWAIT_MAX_SIZE) \
+FLAGDEF(   5, ECX, COMMON,  0,  1, MWAIT_EXTENSIONS,    NA,  FALSE) \
+FLAGDEFA(  5, ECX, COMMON,  1,  1, MWAIT_INTR_BREAK,    NA,  FALSE, MWAIT_INTR_BREAK) \
+FIELDDEF(  5, EDX, INTEL,   0,  4, MWAIT_C0_SUBSTATE,   NA,  FALSE) \
+FIELDDEF(  5, EDX, INTEL,   4,  4, MWAIT_C1_SUBSTATE,   NA,  FALSE) \
+FIELDDEF(  5, EDX, INTEL,   8,  4, MWAIT_C2_SUBSTATE,   NA,  FALSE) \
+FIELDDEF(  5, EDX, INTEL,  12,  4, MWAIT_C3_SUBSTATE,   NA,  FALSE) \
+FIELDDEF(  5, EDX, INTEL,  16,  4, MWAIT_C4_SUBSTATE,   NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_6                                               \
+FLAGDEF(   6, EAX, INTEL,   0,  1, THERMAL_SENSOR,      NA,  FALSE)     \
+FLAGDEF(   6, EAX, INTEL,   1,  1, TURBO_MODE,          NA,  FALSE)     \
+FLAGDEF(   6, EAX, INTEL,   2,  1, APIC_INVARIANT,      NA,  FALSE)     \
+FIELDDEF(  6, EBX, INTEL,   0,  4, NUM_INTR_THRESHOLDS, NA,  FALSE)     \
+FLAGDEF(   6, ECX, INTEL,   0,  1, HW_COORD_FEEDBACK,   NA,  FALSE)	\
+FLAGDEF(   6, ECX, INTEL,   3,  1, ENERGY_PERF_BIAS,    NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_7                                               \
+FLAGDEFA(  7, EBX, INTEL,   0,  1, FSGSBASE,            YES, FALSE, FSGSBASE)  \
+FLAGDEF(   7, EBX, INTEL,   7,  1, SMEP,                NO,  FALSE)            \
+FLAGDEF(   7, EBX, INTEL,   9,  1, ENFSTRG,             YES, FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_A                                               \
+FIELDDEFA( A, EAX, INTEL,   0,  8, PMC_VERSION,         NA,  FALSE, PMC_VERSION) \
+FIELDDEFA( A, EAX, INTEL,   8,  8, NUM_PMCS,            NA,  FALSE, NUM_PMCS)  \
+FIELDDEF(  A, EAX, INTEL,  16,  8, PMC_BIT_WIDTH,       NA,  FALSE)            \
+FIELDDEFA( A, EAX, INTEL,  24,  8, PMC_EBX_LENGTH,      NA,  FALSE, PMC_EBX_LENGTH) \
+FLAGDEF(   A, EBX, INTEL,   0,  1, PMC_CORE_CYCLE,      NA,  FALSE)            \
+FLAGDEF(   A, EBX, INTEL,   1,  1, PMC_INSTR_RETIRED,   NA,  FALSE)            \
+FLAGDEF(   A, EBX, INTEL,   2,  1, PMC_REF_CYCLES,      NA,  FALSE)            \
+FLAGDEF(   A, EBX, INTEL,   3,  1, PMC_LAST_LVL_CREF,   NA,  FALSE)            \
+FLAGDEF(   A, EBX, INTEL,   4,  1, PMC_LAST_LVL_CMISS,  NA,  FALSE)            \
+FLAGDEF(   A, EBX, INTEL,   5,  1, PMC_BR_INST_RETIRED, NA,  FALSE)            \
+FLAGDEF(   A, EBX, INTEL,   6,  1, PMC_BR_MISS_RETIRED, NA,  FALSE)            \
+FIELDDEFA( A, EDX, INTEL,   0,  5, PMC_FIXED_NUM,       NA,  FALSE, NUM_FIXED_PMCS) \
+FIELDDEF(  A, EDX, INTEL,   5,  8, PMC_FIXED_SIZE,      NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_B                                               \
+FIELDDEF(  B, EAX, INTEL,   0,  5, MASK_WIDTH,          NA,  FALSE)            \
+FIELDDEF(  B, EBX, INTEL,   0, 16, CPUS_SHARING_LEVEL,  NA,  FALSE)            \
+FIELDDEF(  B, ECX, INTEL,   0,  8, LEVEL_NUMBER,        NA,  FALSE)            \
+FIELDDEF(  B, ECX, INTEL,   8,  8, LEVEL_TYPE,          NA,  FALSE)            \
+FIELDDEF(  B, EDX, INTEL,   0, 32, X2APIC_ID,           NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_D                                               \
+FLAGDEFA(  D, EAX, COMMON,  0,  1, XCR0_MASTER_LEGACY_FP, YES, FALSE, XCR0_MASTER_LEGACY_FP) \
+FLAGDEFA(  D, EAX, COMMON,  1,  1, XCR0_MASTER_SSE,     YES, FALSE, XCR0_MASTER_SSE) \
+FLAGDEFA(  D, EAX, COMMON,  2,  1, XCR0_MASTER_YMM_H,   YES, FALSE, XCR0_MASTER_YMM_H) \
+FIELDDEF(  D, EAX, COMMON,  3, 29, XCR0_MASTER_LOWER,   NO,  FALSE)            \
+FIELDDEF(  D, EBX, COMMON,  0, 32, XSAVE_ENABLED_SIZE,  ANY, FALSE)            \
+FIELDDEFA( D, ECX, COMMON,  0, 32, XSAVE_MAX_SIZE,      YES, FALSE, XSAVE_MAX_SIZE) \
+FIELDDEF(  D, EDX, COMMON,  0, 32, XCR0_MASTER_UPPER,   NO,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_400                                             \
+FIELDDEF(400, EAX, COMMON,  0, 32, NUM_HYP_LEVELS,      NA,  FALSE)            \
+FIELDDEF(400, EBX, COMMON,  0, 32, HYPERVISOR1,         NA,  FALSE)            \
+FIELDDEF(400, ECX, COMMON,  0, 32, HYPERVISOR2,         NA,  FALSE)            \
+FIELDDEF(400, EDX, COMMON,  0, 32, HYPERVISOR3,         NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_410                                             \
+FIELDDEF(410, EAX, COMMON,  0, 32, TSC_HZ,              NA,  FALSE)            \
+FIELDDEF(410, EBX, COMMON,  0, 32, ACPIBUS_HZ,          NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_80                                              \
+FIELDDEF( 80, EAX, COMMON,  0, 32, NUM_EXT_LEVELS,      NA,  FALSE)            \
+FIELDDEF( 80, EBX, AMD,     0, 32, AMD_VENDOR1,         NA,  FALSE)            \
+FIELDDEF( 80, ECX, AMD,     0, 32, AMD_VENDOR3,         NA,  FALSE)            \
+FIELDDEF( 80, EDX, AMD,     0, 32, AMD_VENDOR2,         NA,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_81                                              \
+FIELDDEF( 81, EAX, INTEL,   0, 32, UNKNOWN81EAX,        ANY, FALSE)            \
+FIELDDEF( 81, EAX, AMD,     0,  4, STEPPING,            ANY, FALSE)            \
+FIELDDEF( 81, EAX, AMD,     4,  4, MODEL,               ANY, FALSE)            \
+FIELDDEF( 81, EAX, AMD,     8,  4, FAMILY,              ANY, FALSE)            \
+FIELDDEF( 81, EAX, AMD,    12,  2, TYPE,                ANY, FALSE)            \
+FIELDDEF( 81, EAX, AMD,    16,  4, EXTMODEL,            ANY, FALSE)            \
+FIELDDEF( 81, EAX, AMD,    20,  8, EXTFAMILY,           ANY, FALSE)            \
+FIELDDEF( 81, EBX, INTEL,   0, 32, UNKNOWN81EBX,        ANY, FALSE)            \
+FIELDDEF( 81, EBX, AMD,     0, 16, BRAND_ID,            ANY, FALSE)            \
+FIELDDEF( 81, EBX, AMD,    16, 16, UNDEF,               ANY, FALSE)            \
+FLAGDEFA( 81, ECX, COMMON,  0,  1, LAHF,                YES, TRUE,  LAHF64)    \
+FLAGDEFA( 81, ECX, AMD,     1,  1, CMPLEGACY,           NO,  FALSE, CMPLEGACY) \
+FLAGDEFA( 81, ECX, AMD,     2,  1, SVM,                 YES, FALSE, SVM)       \
+FLAGDEFA( 81, ECX, AMD,     3,  1, EXTAPICSPC,          YES, FALSE, EXTAPICSPC) \
+FLAGDEFA( 81, ECX, AMD,     4,  1, CR8AVAIL,            NO,  FALSE, CR8AVAIL)  \
+FLAGDEFA( 81, ECX, AMD,     5,  1, ABM,                 YES, TRUE,  ABM)       \
+FLAGDEFA( 81, ECX, AMD,     6,  1, SSE4A,               YES, TRUE,  SSE4A)     \
+FLAGDEF(  81, ECX, AMD,     7,  1, MISALIGNED_SSE,      YES, TRUE)             \
+FLAGDEFA( 81, ECX, AMD,     8,  1, 3DNPREFETCH,         YES, TRUE, 3DNPREFETCH) \
+FLAGDEFA( 81, ECX, AMD,     9,  1, OSVW,                ANY, FALSE, OSVW)      \
+FLAGDEF(  81, ECX, AMD,    10,  1, IBS,                 NO,  FALSE)            \
+FLAGDEFA( 81, ECX, AMD,    11,  1, XOP,                 YES, TRUE,  XOP)       \
+FLAGDEF(  81, ECX, AMD,    12,  1, SKINIT,              NO,  FALSE)            \
+FLAGDEF(  81, ECX, AMD,    13,  1, WATCHDOG,            NO,  FALSE)            \
+FLAGDEF(  81, ECX, AMD,    15,  1, LWP,                 NO,  FALSE)            \
+FLAGDEFA( 81, ECX, AMD,    16,  1, FMA4,                YES, TRUE,  FMA4)      \
+FLAGDEF(  81, ECX, AMD,    19,  1, NODEID,              NO,  FALSE)            \
+FLAGDEF(  81, ECX, AMD,    22,  1, TOPOLOGY,            NO,  FALSE)            \
+FLAGDEF(  81, ECX, AMD,    23,  1, PERFCTR_EXT_NB,      NO,  FALSE)            \
+FLAGDEF(  81, ECX, AMD,    24,  1, PREFCTR_EXT_CORE,    NO,  FALSE)            \
+FLAGDEF(  81, EDX, AMD,     0,  1, FPU,                 YES, TRUE)             \
+FLAGDEF(  81, EDX, AMD,     1,  1, VME,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,     2,  1, DBGE,                YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,     3,  1, PGSZE,               YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,     4,  1, TSC,                 YES, TRUE)             \
+FLAGDEF(  81, EDX, AMD,     5,  1, MSR,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,     6,  1, PAE,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,     7,  1, MCK,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,     8,  1, CPMX,                YES, TRUE)             \
+FLAGDEF(  81, EDX, AMD,     9,  1, APIC,                ANY, FALSE)            \
+FLAGDEFA( 81, EDX, COMMON, 11,  1, SYSC,                ANY, TRUE, SYSC)       \
+FLAGDEF(  81, EDX, AMD,    12,  1, MTRR,                YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,    13,  1, PGE,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,    14,  1, MCA,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,    15,  1, CMOV,                YES, TRUE)             \
+FLAGDEF(  81, EDX, AMD,    16,  1, PAT,                 YES, FALSE)            \
+FLAGDEF(  81, EDX, AMD,    17,  1, 36PG,                YES, FALSE)            \
+FLAGDEFA( 81, EDX, COMMON, 20,  1, NX,                  YES, FALSE, NX)        \
+FLAGDEFA( 81, EDX, AMD,    22,  1, MMXEXT,              YES, TRUE,  MMXEXT)    \
+FLAGDEF(  81, EDX, AMD,    23,  1, MMX,                 YES, TRUE)             \
+FLAGDEF(  81, EDX, AMD,    24,  1, FXSAVE,              YES, TRUE)             \
+FLAGDEFA( 81, EDX, AMD,    25,  1, FFXSR,               YES, FALSE, FFXSR)     \
+FLAGDEF(  81, EDX, COMMON, 26,  1, PDPE1GB,             NO,  FALSE)            \
+FLAGDEFA( 81, EDX, COMMON, 27,  1, RDTSCP,              YES, TRUE,  RDTSCP)    \
+FLAGDEFA( 81, EDX, COMMON, 29,  1, LM,                  YES, FALSE, LM) \
+FLAGDEFA( 81, EDX, AMD,    30,  1, 3DNOWPLUS,           YES, TRUE,  3DNOWPLUS) \
+FLAGDEFA( 81, EDX, AMD,    31,  1, 3DNOW,               YES, TRUE,  3DNOW)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_8x                                              \
+FIELDDEF( 85, EAX, AMD,     0,  8, ITLB_ENTRIES_2M4M_PGS, NA, FALSE)           \
+FIELDDEF( 85, EAX, AMD,     8,  8, ITLB_ASSOC_2M4M_PGS, NA,  FALSE)            \
+FIELDDEF( 85, EAX, AMD,    16,  8, DTLB_ENTRIES_2M4M_PGS, NA, FALSE)           \
+FIELDDEF( 85, EAX, AMD,    24,  8, DTLB_ASSOC_2M4M_PGS, NA,  FALSE)            \
+FIELDDEF( 85, EBX, AMD,     0,  8, ITLB_ENTRIES_4K_PGS, NA,  FALSE)            \
+FIELDDEF( 85, EBX, AMD,     8,  8, ITLB_ASSOC_4K_PGS,   NA,  FALSE)            \
+FIELDDEF( 85, EBX, AMD,    16,  8, DTLB_ENTRIES_4K_PGS, NA,  FALSE)            \
+FIELDDEF( 85, EBX, AMD,    24,  8, DTLB_ASSOC_4K_PGS,   NA,  FALSE)            \
+FIELDDEF( 85, ECX, AMD,     0,  8, L1_DCACHE_LINE_SIZE, NA,  FALSE)            \
+FIELDDEF( 85, ECX, AMD,     8,  8, L1_DCACHE_LINES_PER_TAG, NA, FALSE)         \
+FIELDDEF( 85, ECX, AMD,    16,  8, L1_DCACHE_ASSOC,     NA, FALSE)             \
+FIELDDEF( 85, ECX, AMD,    24,  8, L1_DCACHE_SIZE,      NA, FALSE)             \
+FIELDDEF( 85, EDX, AMD,     0,  8, L1_ICACHE_LINE_SIZE, NA,  FALSE)            \
+FIELDDEF( 85, EDX, AMD,     8,  8, L1_ICACHE_LINES_PER_TAG, NA, FALSE)         \
+FIELDDEF( 85, EDX, AMD,    16,  8, L1_ICACHE_ASSOC,     NA, FALSE)             \
+FIELDDEF( 85, EDX, AMD,    24,  8, L1_ICACHE_SIZE,      NA, FALSE)             \
+FIELDDEF( 86, EAX, AMD,     0, 12, L2_ITLB_ENTRIES_2M4M_PGS, NA, FALSE)        \
+FIELDDEF( 86, EAX, AMD,    12,  4, L2_ITLB_ASSOC_2M4M_PGS, NA, FALSE)          \
+FIELDDEF( 86, EAX, AMD,    16, 12, L2_DTLB_ENTRIES_2M4M_PGS, NA, FALSE)        \
+FIELDDEF( 86, EAX, AMD,    28,  4, L2_DTLB_ASSOC_2M4M_PGS, NA, FALSE)          \
+FIELDDEF( 86, EBX, AMD,     0, 12, L2_ITLB_ENTRIES_4K_PGS, NA, FALSE)          \
+FIELDDEF( 86, EBX, AMD,    12,  4, L2_ITLB_ASSOC_4K_PGS, NA, FALSE)            \
+FIELDDEF( 86, EBX, AMD,    16, 12, L2_DTLB_ENTRIES_4K_PGS, NA, FALSE)          \
+FIELDDEF( 86, EBX, AMD,    28,  4, L2_DTLB_ASSOC_4K_PGS,NA,  FALSE)            \
+FIELDDEF( 86, ECX, AMD,     0,  8, L2CACHE_LINE,        NA,  FALSE)            \
+FIELDDEF( 86, ECX, AMD,     8,  4, L2CACHE_LINE_PER_TAG,NA,  FALSE)            \
+FIELDDEF( 86, ECX, AMD,    12,  4, L2CACHE_WAYS,        NA,  FALSE)            \
+FIELDDEF( 86, ECX, AMD,    16, 16, L2CACHE_SIZE,        NA,  FALSE)            \
+FIELDDEF( 86, EDX, AMD,     0,  8, L3CACHE_LINE,        NA,  FALSE)            \
+FIELDDEF( 86, EDX, AMD,     8,  4, L3CACHE_LINE_PER_TAG,NA,  FALSE)            \
+FIELDDEF( 86, EDX, AMD,    12,  4, L3CACHE_WAYS,        NA,  FALSE)            \
+FIELDDEF( 86, EDX, AMD,    18, 14, L3CACHE_SIZE,        NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     0,  1, TS,                  NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     1,  1, FID,                 NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     2,  1, VID,                 NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     3,  1, TTP,                 NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     4,  1, TM,                  NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     5,  1, STC,                 NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     6,  1, 100MHZSTEPS,         NA,  FALSE)            \
+FLAGDEF(  87, EDX, AMD,     7,  1, HWPSTATE,            NA,  FALSE)            \
+FLAGDEF(  87, EDX, COMMON,  8,  1, TSC_INVARIANT,       NA,  FALSE)            \
+FLAGDEF(  87, EDX, COMMON,  9,  1, CORE_PERF_BOOST,     NA,  FALSE)            \
+FIELDDEFA(88, EAX, COMMON,  0,  8, PHYSBITS,            NA,  FALSE, PHYS_BITS) \
+FIELDDEFA(88, EAX, COMMON,  8,  8, VIRTBITS,            NA,  FALSE, VIRT_BITS) \
+FIELDDEF( 88, EAX, COMMON, 16,  8, GUEST_PHYS_ADDR_SZ,  NA,  FALSE)            \
+FIELDDEFA(88, ECX, AMD,     0,  8, CORE_COUNT,          NA,  FALSE, AMD_CORE_COUNT) \
+FIELDDEFA(88, ECX, AMD,    12,  4, APICID_COREID_SIZE,  NA,  FALSE, AMD_APICID_COREID_SIZE) \
+FIELDDEFA(8A, EAX, AMD,     0,  8, SVM_REVISION,        YES, FALSE, SVM_REVISION) \
+FLAGDEF(  8A, EAX, AMD,     8,  1, SVM_HYPERVISOR,      NO,  FALSE)            \
+FIELDDEF( 8A, EAX, AMD,     9, 23, SVMEAX_RSVD,         NO,  FALSE)            \
+FIELDDEFA(8A, EBX, AMD,     0, 32, SVM_N_ASIDS,         YES, FALSE, SVM_NUM_ASIDS) \
+FIELDDEF( 8A, ECX, AMD,     0, 32, SVMECX_RSVD,         NO,  FALSE)            \
+FLAGDEFA( 8A, EDX, AMD,     0,  1, SVM_NP,              YES, FALSE, NPT)       \
+FLAGDEF(  8A, EDX, AMD,     1,  1, SVM_LBR,             NO,  FALSE)            \
+FLAGDEFA( 8A, EDX, AMD,     2,  1, SVM_LOCK,            YES, FALSE, SVM_LOCK)  \
+FLAGDEFA( 8A, EDX, AMD,     3,  1, SVM_NRIP,            YES, FALSE, SVM_NRIP)  \
+FLAGDEF(  8A, EDX, AMD,     4,  1, SVM_TSC_RATE_MSR,    NO,  FALSE)            \
+FLAGDEF(  8A, EDX, AMD,     5,  1, SVM_VMCB_CLEAN,      YES, FALSE)            \
+FLAGDEF(  8A, EDX, AMD,     6,  1, SVM_FLUSH_BY_ASID,   YES, FALSE)            \
+FLAGDEFA( 8A, EDX, AMD,     7,  1, SVM_DECODE_ASSISTS,  YES, FALSE, SVM_DECODE_ASSISTS) \
+FIELDDEF( 8A, EDX, AMD,     8,  2, SVMEDX_RSVD0,        NO,  FALSE)            \
+FLAGDEFA( 8A, EDX, AMD,    10,  1, SVM_PAUSE_FILTER,    NO,  FALSE, PAUSE_FILTER) \
+FLAGDEF(  8A, EDX, AMD,    11,  1, SVMEDX_RSVD1,        NO,  FALSE)            \
+FLAGDEF(  8A, EDX, AMD,    12,  1, SVM_PAUSE_THRESHOLD, NO,  FALSE)            \
+FIELDDEF( 8A, EDX, AMD,    13, 19, SVMEDX_RSVD2,        NO,  FALSE)
+
+/*    LEVEL, REG, VENDOR, POS, SIZE, NAME,       MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_81x                                             \
+FIELDDEF(819, EAX, AMD,     0, 12, L1_ITLB_ENTRIES_1G_PGS, NA, FALSE)          \
+FIELDDEF(819, EAX, AMD,    12,  4, L1_ITLB_ASSOC_1G_PGS, NA, FALSE)            \
+FIELDDEF(819, EAX, AMD,    16, 12, L1_DTLB_ENTRIES_1G_PGS, NA, FALSE)          \
+FIELDDEF(819, EAX, AMD,    28,  4, L1_DTLB_ASSOC_1G_PGS, NA, FALSE)            \
+FIELDDEF(819, EBX, AMD,     0, 12, L2_ITLB_ENTRIES_1G_PGS, NA, FALSE)          \
+FIELDDEF(819, EBX, AMD,    12,  4, L2_ITLB_ASSOC_1G_PGS, NA, FALSE)            \
+FIELDDEF(819, EBX, AMD,    16, 12, L2_DTLB_ENTRIES_1G_PGS, NA, FALSE)          \
+FIELDDEF(819, EBX, AMD,    28,  4, L2_DTLB_ASSOC_1G_PGS, NA, FALSE)            \
+FLAGDEF( 81A, EAX, AMD,     0,  1, FP128,               NA,  FALSE)            \
+FLAGDEF( 81A, EAX, AMD,     1,  1, MOVU,                NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     0,  1, IBS_FFV,             NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     1,  1, IBS_FETCHSAM,        NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     2,  1, IBS_OPSAM,           NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     3,  1, RW_OPCOUNT,          NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     4,  1, OPCOUNT,             NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     5,  1, BRANCH_TARGET_ADDR,  NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     6,  1, OPCOUNT_EXT,         NA,  FALSE)            \
+FLAGDEF( 81B, EAX, AMD,     7,  1, RIP_INVALID_CHECK,   NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     0,  1, LWP_AVAIL,           NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     1,  1, LWP_VAL_AVAIL,       NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     2,  1, LWP_IRE_AVAIL,       NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     3,  1, LWP_BRE_AVAIL,       NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     4,  1, LWP_DME_AVAIL,       NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     5,  1, LWP_CNH_AVAIL,       NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,     6,  1, LWP_RNH_AVAIL,       NA,  FALSE)            \
+FLAGDEF( 81C, EAX, AMD,    31,  1, LWP_INT_AVAIL,       NA,  FALSE)            \
+FIELDDEF(81C, EBX, AMD,     0,  8, LWP_CB_SIZE,         NA,  FALSE)            \
+FIELDDEF(81C, EBX, AMD,     8,  8, LWP_EVENT_SIZE,      NA,  FALSE)            \
+FIELDDEF(81C, EBX, AMD,    16,  8, LWP_MAX_EVENTS,      NA,  FALSE)            \
+FIELDDEF(81C, EBX, AMD,    24,  8, LWP_EVENT_OFFSET,    NA,  FALSE)            \
+FIELDDEF(81C, ECX, AMD,     0,  4, LWP_LATENCY_MAX,     NA,  FALSE)            \
+FLAGDEF( 81C, ECX, AMD,     5,  1, LWP_DATA_ADDR_VALID, NA,  FALSE)            \
+FIELDDEF(81C, ECX, AMD,     6,  3, LWP_LATENCY_ROUND,   NA,  FALSE)            \
+FIELDDEF(81C, ECX, AMD,     9,  7, LWP_VERSION,         NA,  FALSE)            \
+FIELDDEF(81C, ECX, AMD,    16,  8, LWP_MIN_BUF_SIZE,    NA,  FALSE)            \
+FLAGDEF( 81C, ECX, AMD,    28,  1, LWP_BRANCH_PRED,     NA,  FALSE)            \
+FLAGDEF( 81C, ECX, AMD,    29,  1, LWP_IP_FILTERING,    NA,  FALSE)            \
+FLAGDEF( 81C, ECX, AMD,    30,  1, LWP_CACHE_LEVEL,     NA,  FALSE)            \
+FLAGDEF( 81C, ECX, AMD,    31,  1, LWP_CACHE_LATENCY,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     0,  1, LWP_SUPPORTED,       NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     1,  1, LWP_VAL_SUPPORTED,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     2,  1, LWP_IRE_SUPPORTED,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     3,  1, LWP_BRE_SUPPORTED,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     4,  1, LWP_DME_SUPPORTED,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     5,  1, LWP_CNH_SUPPORTED,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,     6,  1, LWP_RNH_SUPPORTED,   NA,  FALSE)            \
+FLAGDEF( 81C, EDX, AMD,    31,  1, LWP_INT_SUPPORTED,   NA,  FALSE)            \
+FIELDDEFA( 81D,EAX, AMD,     0,  5, CACHE_TYPE,          NA,  FALSE, AMD_CACHE_TYPE) \
+FIELDDEFA( 81D,EAX, AMD,     5,  3, CACHE_LEVEL,         NA,  FALSE, AMD_CACHE_LEVEL) \
+FLAGDEF( 81D, EAX, AMD,     8,  1, CACHE_SELF_INIT,     NA,  FALSE)            \
+FLAGDEF( 81D, EAX, AMD,     9,  1, CACHE_FULLY_ASSOC,   NA,  FALSE)            \
+FIELDDEFA(81D, EAX, AMD,    14, 12, NUM_SHARING_CACHE,   NA,  FALSE, AMD_NUM_SHARING_CACHE)            \
+FIELDDEF(81D, EBX, AMD,     0, 12, CACHE_LINE_SIZE,     NA,  FALSE)            \
+FIELDDEF(81D, EBX, AMD,    12, 10, CACHE_PHYS_PARTITIONS, NA, FALSE)           \
+FIELDDEFA(81D,EBX, AMD,   22, 10, CACHE_WAYS,          NA,  FALSE, AMD_CACHE_WAYS) \
+FIELDDEF(81D, ECX, AMD,     0, 32, CACHE_NUM_SETS,      NA,  FALSE)            \
+FLAGDEF( 81D, EDX, AMD,     0,  1, CACHE_WBINVD,        NA,  FALSE)            \
+FLAGDEF( 81D, EDX, AMD,     1,  1, CACHE_INCLUSIVE,     NA,  FALSE)            \
+FIELDDEF(81E, EAX, AMD,     0, 32, EXTENDED_APICID,     NA,  FALSE)            \
+FIELDDEF(81E, EBX, AMD,     0,  8, COMPUTE_UNIT_ID,     NA,  FALSE)            \
+FIELDDEFA(81E, EBX, AMD,     8,  2, CORES_PER_COMPUTE_UNIT, NA, FALSE, AMD_CORES_PER_COMPUTE_UNIT)          \
+FIELDDEF(81E, ECX, AMD,     0,  8, NODEID,              NA,  FALSE)            \
+FIELDDEFA( 81E,ECX, AMD,     8,  3, NODES_PER_PKG,       NA,  FALSE, AMD_NODES_PER_PKG)
+
+#define INTEL_CPUID_FIELD_DATA
+
+#define AMD_CPUID_FIELD_DATA
+
+#define CPUID_FIELD_DATA                                              \
+   CPUID_FIELD_DATA_LEVEL_0                                           \
+   CPUID_FIELD_DATA_LEVEL_1                                           \
+   CPUID_FIELD_DATA_LEVEL_4                                           \
+   CPUID_FIELD_DATA_LEVEL_5                                           \
+   CPUID_FIELD_DATA_LEVEL_6                                           \
+   CPUID_FIELD_DATA_LEVEL_7                                           \
+   CPUID_FIELD_DATA_LEVEL_A                                           \
+   CPUID_FIELD_DATA_LEVEL_B                                           \
+   CPUID_FIELD_DATA_LEVEL_D                                           \
+   CPUID_FIELD_DATA_LEVEL_400                                         \
+   CPUID_FIELD_DATA_LEVEL_410                                         \
+   CPUID_FIELD_DATA_LEVEL_80                                          \
+   CPUID_FIELD_DATA_LEVEL_81                                          \
+   CPUID_FIELD_DATA_LEVEL_8x                                          \
+   CPUID_FIELD_DATA_LEVEL_81x                                         \
+   INTEL_CPUID_FIELD_DATA                                             \
+   AMD_CPUID_FIELD_DATA
+
+/*
+ * Define all field and flag values as an enum.  The result is a full
+ * set of values taken from the table above in the form:
+ *
+ * CPUID_FEATURE_<vendor>_ID<level><reg>_<name> == mask for feature
+ * CPUID_<vendor>_ID<level><reg>_<name>_MASK    == mask for field
+ * CPUID_<vendor>_ID<level><reg>_<name>_SHIFT   == offset of field
+ *
+ * e.g. - CPUID_FEATURE_COMMON_ID1EDX_FPU     = 0x1
+ *      - CPUID_COMMON_ID88EAX_VIRTBITS_MASK  = 0xff00
+ *      - CPUID_COMMON_ID88EAX_VIRTBITS_SHIFT = 8
+ *
+ * Note: The FEATURE/MASK definitions must use some gymnastics to get
+ * around a warning when shifting left by 32.
+ */
+#define VMW_BIT_MASK(shift)  (((1 << (shift - 1)) << 1) - 1)
+
+#define FIELDDEF(lvl, reg, vend, bitpos, size, name, s, c3)             \
+   CPUID_##vend##_ID##lvl##reg##_##name##_SHIFT = bitpos,               \
+   CPUID_##vend##_ID##lvl##reg##_##name##_MASK  =                       \
+                      VMW_BIT_MASK(size) << bitpos,                     \
+   CPUID_FEATURE_##vend##_ID##lvl##reg##_##name =                       \
+                      CPUID_##vend##_ID##lvl##reg##_##name##_MASK,
+
+/* Before simplifying this take a look at bug 293638... */
+#define FIELDDEFA(lvl, reg, vend, bitpos, size, name, s, c3, f)         \
+   CPUID_##vend##_ID##lvl##reg##_##name##_SHIFT = bitpos,               \
+   CPUID_##vend##_ID##lvl##reg##_##name##_MASK  =                       \
+                      VMW_BIT_MASK(size) << bitpos,                     \
+   CPUID_FEATURE_##vend##_ID##lvl##reg##_##name =                       \
+                      CPUID_##vend##_ID##lvl##reg##_##name##_MASK,
+
+#define FLAGDEFA FIELDDEFA
+#define FLAGDEF FIELDDEF
+
+enum {
+   /* Define data for every CPUID field we have */
+   CPUID_FIELD_DATA
+};
+#undef VMW_BIT_MASK
+#undef FIELDDEF
+#undef FLAGDEF
+#undef FIELDDEFA
+#undef FLAGDEFA
+
+/* Level D subleaf 1 eax XSAVEOPT */
+#define CPUID_COMMON_IDDsub1EAX_XSAVEOPT 1
+
+/*
+ * Legal CPUID config file mask characters.  For a description of the
+ * cpuid masking system, please see:
+ *
+ * http://vmweb.vmware.com/~mts/cgi-bin/view.cgi/Apps/CpuMigrationChecks
+ */
+
+#define CPUID_MASK_HIDE_CHR    '0'
+#define CPUID_MASK_HIDE_STR    "0"
+#define CPUID_MASK_FORCE_CHR   '1'
+#define CPUID_MASK_FORCE_STR   "1"
+#define CPUID_MASK_PASS_CHR    '-'
+#define CPUID_MASK_PASS_STR    "-"
+#define CPUID_MASK_TRUE_CHR    'T'
+#define CPUID_MASK_TRUE_STR    "T"
+#define CPUID_MASK_FALSE_CHR   'F'
+#define CPUID_MASK_FALSE_STR   "F"
+#define CPUID_MASK_IGNORE_CHR  'X'
+#define CPUID_MASK_IGNORE_STR  "X"
+#define CPUID_MASK_HOST_CHR    'H'
+#define CPUID_MASK_HOST_STR    "H"
+#define CPUID_MASK_RSVD_CHR    'R'
+#define CPUID_MASK_RSVD_STR    "R"
+#define CPUID_MASK_INSTALL_CHR 'I'
+#define CPUID_MASK_INSTALL_STR "I"
+
+/*
+ * When LM is disabled, we overlay the following masks onto the
+ * guest's default masks.  Any level that is not defined below should
+ * be treated as all "-"s
+ */
+
+#define CPT_ID1ECX_LM_DISABLED  "----:----:----:----:--0-:----:----:----"
+#define CPT_ID81EDX_LM_DISABLED "--0-:----:----:----:----:----:----:----"
+#define CPT_ID81ECX_LM_DISABLED "----:----:----:----:----:----:----:---0"
+
+#define CPT_GET_LM_DISABLED_MASK(lvl, reg)                                  \
+   ((lvl == 1 && reg == CPUID_REG_ECX) ? CPT_ID1ECX_LM_DISABLED :           \
+    (lvl == 0x80000001 && reg == CPUID_REG_ECX) ? CPT_ID81ECX_LM_DISABLED : \
+    (lvl == 0x80000001 && reg == CPUID_REG_EDX) ? CPT_ID81EDX_LM_DISABLED : \
+    NULL)
+
+/*
+ * Macro to define GET and SET functions for various common CPUID
+ * fields.  To create function for a new field, simply name it (CPUID_
+ * and CPUID_SET_ are automatically prepended), and list the field
+ * name that it needs to use.
+ */
+
+#define FIELD_FUNC(name, field)                                 \
+   static INLINE uint32 CPUID_##name(uint32 reg)                \
+   {                                                            \
+      return (reg & field##_MASK) >> field##_SHIFT;             \
+   }                                                            \
+   static INLINE void CPUID_SET_##name(uint32 *reg, uint32 val) \
+   {                                                            \
+      *reg = (*reg & ~field##_MASK) | (val << field##_SHIFT);   \
+   }
+
+FIELD_FUNC(STEPPING,         CPUID_COMMON_ID1EAX_STEPPING)
+FIELD_FUNC(MODEL,            CPUID_COMMON_ID1EAX_MODEL)
+FIELD_FUNC(FAMILY,           CPUID_COMMON_ID1EAX_FAMILY)
+FIELD_FUNC(TYPE,             CPUID_COMMON_ID1EAX_TYPE)
+FIELD_FUNC(EXTENDED_MODEL,   CPUID_COMMON_ID1EAX_EXTMODEL)
+FIELD_FUNC(EXTENDED_FAMILY,  CPUID_COMMON_ID1EAX_EXTFAMILY)
+FIELD_FUNC(LCPU_COUNT,       CPUID_COMMON_ID1EBX_LCPU_COUNT)
+FIELD_FUNC(APICID,           CPUID_COMMON_ID1EBX_APICID)
+FIELD_FUNC(PA_BITS,          CPUID_COMMON_ID88EAX_PHYSBITS)
+FIELD_FUNC(VIRT_BITS,        CPUID_COMMON_ID88EAX_VIRTBITS)
+FIELD_FUNC(SVM_REVISION,     CPUID_AMD_ID8AEAX_SVM_REVISION)
+FIELD_FUNC(SVM_N_ASIDS,      CPUID_AMD_ID8AEBX_SVM_N_ASIDS)
+FIELD_FUNC(CACHE_TYPE,       CPUID_INTEL_ID4EAX_CACHE_TYPE)
+FIELD_FUNC(INTEL_CORE_COUNT, CPUID_INTEL_ID4EAX_CORE_COUNT)
+FIELD_FUNC(AMD_CORE_COUNT,   CPUID_AMD_ID88ECX_CORE_COUNT)
+FIELD_FUNC(AMD_APICID_COREID_SIZE, CPUID_AMD_ID88ECX_APICID_COREID_SIZE)
+FIELD_FUNC(AMD_EXTAPICSPC,   CPUID_AMD_ID81ECX_EXTAPICSPC)
+FIELD_FUNC(NUM_PMCS,         CPUID_INTEL_IDAEAX_NUM_PMCS)
+FIELD_FUNC(MWAIT_MIN_SIZE,   CPUID_COMMON_ID5EAX_MWAIT_MIN_SIZE)
+FIELD_FUNC(MWAIT_MAX_SIZE,   CPUID_COMMON_ID5EBX_MWAIT_MAX_SIZE)
+FIELD_FUNC(MWAIT_C0_SUBSTATE, CPUID_INTEL_ID5EDX_MWAIT_C0_SUBSTATE)
+FIELD_FUNC(MWAIT_C1_SUBSTATE, CPUID_INTEL_ID5EDX_MWAIT_C1_SUBSTATE)
+FIELD_FUNC(MWAIT_C2_SUBSTATE, CPUID_INTEL_ID5EDX_MWAIT_C2_SUBSTATE)
+FIELD_FUNC(MWAIT_C3_SUBSTATE, CPUID_INTEL_ID5EDX_MWAIT_C3_SUBSTATE)
+FIELD_FUNC(MWAIT_C4_SUBSTATE, CPUID_INTEL_ID5EDX_MWAIT_C4_SUBSTATE)
+FIELD_FUNC(TOPOLOGY_MASK_WIDTH,         CPUID_INTEL_IDBEAX_MASK_WIDTH)
+FIELD_FUNC(TOPOLOGY_CPUS_SHARING_LEVEL, CPUID_INTEL_IDBEBX_CPUS_SHARING_LEVEL)
+FIELD_FUNC(TOPOLOGY_LEVEL_NUMBER,       CPUID_INTEL_IDBECX_LEVEL_NUMBER)
+FIELD_FUNC(TOPOLOGY_LEVEL_TYPE,         CPUID_INTEL_IDBECX_LEVEL_TYPE)
+FIELD_FUNC(TOPOLOGY_X2APIC_ID,          CPUID_INTEL_IDBEDX_X2APIC_ID)
+FIELD_FUNC(AMD_CACHE_TYPE,      CPUID_AMD_ID81DEAX_CACHE_TYPE)
+FIELD_FUNC(AMD_CACHE_LEVEL,     CPUID_AMD_ID81DEAX_CACHE_LEVEL)
+FIELD_FUNC(AMD_CACHE_WAYS,      CPUID_AMD_ID81DEBX_CACHE_WAYS)
+FIELD_FUNC(AMD_NODES_PER_PKG,   CPUID_AMD_ID81EECX_NODES_PER_PKG)
+FIELD_FUNC(AMD_NUM_SHARING_CACHE, CPUID_AMD_ID81DEAX_NUM_SHARING_CACHE)
+FIELD_FUNC(AMD_CORES_PER_COMPUTE_UNIT, CPUID_AMD_ID81EEBX_CORES_PER_COMPUTE_UNIT)
+#undef FIELD_FUNC
+
+
+/*
+ * Definitions of various fields' values and more complicated
+ * macros/functions for reading cpuid fields.
+ */
+
+#define CPUID_FAMILY_EXTENDED 15
+
+/* Effective Intel CPU Families */
+#define CPUID_FAMILY_486      4
+#define CPUID_FAMILY_P5       5
+#define CPUID_FAMILY_P6       6
+#define CPUID_FAMILY_P4       15
+
+/* Effective AMD CPU Families */
+#define CPUID_FAMILY_5x86     4
+#define CPUID_FAMILY_K5       5
+#define CPUID_FAMILY_K6       5
+#define CPUID_FAMILY_K7       6
+#define CPUID_FAMILY_K8       15
+#define CPUID_FAMILY_K8L      16
+#define CPUID_FAMILY_K8MOBILE 17
+#define CPUID_FAMILY_LLANO    18
+#define CPUID_FAMILY_BOBCAT   20
+#define CPUID_FAMILY_BULLDOZER 21
+
+/* Effective VIA CPU Families */
+#define CPUID_FAMILY_C7       6
+
+/* Intel model information */
+#define CPUID_MODEL_PPRO       1
+#define CPUID_MODEL_PII_03     3
+#define CPUID_MODEL_PII_05     5
+#define CPUID_MODEL_CELERON_06 6
+#define CPUID_MODEL_PM_09      9
+#define CPUID_MODEL_PM_0D      13
+#define CPUID_MODEL_PM_0E      14    // Yonah / Sossaman
+#define CPUID_MODEL_CORE_0F    15    // Conroe / Merom
+#define CPUID_MODEL_CORE_17    0x17  // Penryn
+#define CPUID_MODEL_NEHALEM_1A 0x1a  // Nehalem / Gainestown
+#define CPUID_MODEL_ATOM_1C    0x1c  // Silverthorne / Diamondville
+#define CPUID_MODEL_CORE_1D    0x1d  // Dunnington
+#define CPUID_MODEL_NEHALEM_1E 0x1e  // Lynnfield
+#define CPUID_MODEL_NEHALEM_1F 0x1f  // Havendale
+#define CPUID_MODEL_NEHALEM_25 0x25  // Westmere / Clarkdale
+#define CPUID_MODEL_NEHALEM_2C 0x2c  // Westmere-EP
+#define CPUID_MODEL_NEHALEM_2E 0x2e  // Nehalem-EX
+
+#define CPUID_MODEL_PIII_07    7
+#define CPUID_MODEL_PIII_08    8
+#define CPUID_MODEL_PIII_0A    10
+
+/* AMD model information */
+#define CPUID_MODEL_BARCELONA_02 0x02 // Barcelona (both Opteron & Phenom kind)
+
+/* VIA model information */
+#define CPUID_MODEL_NANO       15     // Isaiah
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CPUID_IsVendor{AMD,Intel,VIA} --
+ *
+ *      Determines if the vendor string in cpuid id0 is from {AMD,Intel,VIA}.
+ *
+ * Results:
+ *      True iff vendor string is CPUID_{AMD,INTEL,VIA}_VENDOR_STRING
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+static INLINE Bool
+CPUID_IsRawVendor(CPUIDRegs *id0, const char* vendor)
+{
+   // hard to get strcmp() in some environments, so do it in the raw
+   return (id0->ebx == *(const uint32 *) (vendor + 0) &&
+           id0->ecx == *(const uint32 *) (vendor + 4) &&
+           id0->edx == *(const uint32 *) (vendor + 8));
+}
+
+static INLINE Bool
+CPUID_IsVendorAMD(CPUIDRegs *id0)
+{
+   return CPUID_IsRawVendor(id0, CPUID_AMD_VENDOR_STRING);
+}
+
+static INLINE Bool
+CPUID_IsVendorIntel(CPUIDRegs *id0)
+{
+   return CPUID_IsRawVendor(id0, CPUID_INTEL_VENDOR_STRING);
+}
+
+static INLINE Bool
+CPUID_IsVendorVIA(CPUIDRegs *id0)
+{
+   return CPUID_IsRawVendor(id0, CPUID_VIA_VENDOR_STRING);
+}
+
+static INLINE uint32
+CPUID_EFFECTIVE_FAMILY(uint32 v) /* %eax from CPUID with %eax=1. */
+{
+   return CPUID_FAMILY(v) +
+      (CPUID_FAMILY(v) == CPUID_FAMILY_EXTENDED ? CPUID_EXTENDED_FAMILY(v) : 0);
+}
+
+/* Normally only used when FAMILY==CPUID_FAMILY_EXTENDED, but Intel is
+ * now using the extended model field for FAMILY==CPUID_FAMILY_P6 to
+ * refer to the newer Core2 CPUs
+ */
+static INLINE uint32
+CPUID_EFFECTIVE_MODEL(uint32 v) /* %eax from CPUID with %eax=1. */
+{
+   return CPUID_MODEL(v) + (CPUID_EXTENDED_MODEL(v) << 4);
+}
+
+/*
+ * Notice that CPUID families for Intel and AMD overlap. The following macros
+ * should only be used AFTER the manufacturer has been established (through
+ * the use of CPUID standard function 0).
+ */
+static INLINE Bool
+CPUID_FAMILY_IS_486(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_486;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_P5(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_P5;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_P6(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_P6;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_PENTIUM4(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_P4;
+}
+
+/*
+ * Intel Pentium M processors are Yonah/Sossaman or an older P-M
+ */
+static INLINE Bool
+CPUID_UARCH_IS_PENTIUM_M(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+   /* Assumes the CPU manufacturer is Intel. */
+   return CPUID_FAMILY_IS_P6(v) &&
+          (CPUID_EFFECTIVE_MODEL(v) == CPUID_MODEL_PM_09 ||
+           CPUID_EFFECTIVE_MODEL(v) == CPUID_MODEL_PM_0D ||
+           CPUID_EFFECTIVE_MODEL(v) == CPUID_MODEL_PM_0E);
+}
+
+/*
+ * Intel Core processors are Merom, Conroe, Woodcrest, Clovertown,
+ * Penryn, Dunnington, Kentsfield, Yorktown, Harpertown, ........
+ */
+static INLINE Bool
+CPUID_UARCH_IS_CORE(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+   uint32 model = CPUID_EFFECTIVE_MODEL(v);
+   /* Assumes the CPU manufacturer is Intel. */
+   return CPUID_FAMILY_IS_P6(v) &&
+          model >= CPUID_MODEL_CORE_0F &&
+          (model < CPUID_MODEL_NEHALEM_1A ||
+           model == CPUID_MODEL_CORE_1D);
+}
+
+/*
+ * Intel Nehalem processors are: Nehalem, Gainestown, Lynnfield, Clarkdale.
+ */
+static INLINE Bool
+CPUID_UARCH_IS_NEHALEM(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+   /* Assumes the CPU manufacturer is Intel. */
+   uint32 effectiveModel = CPUID_EFFECTIVE_MODEL(v);
+
+   return CPUID_FAMILY_IS_P6(v) &&
+          (
+           effectiveModel == CPUID_MODEL_NEHALEM_1A ||
+           effectiveModel == CPUID_MODEL_NEHALEM_1E ||
+           effectiveModel == CPUID_MODEL_NEHALEM_1F ||
+           effectiveModel == CPUID_MODEL_NEHALEM_25 ||
+           effectiveModel == CPUID_MODEL_NEHALEM_2C ||
+           effectiveModel == CPUID_MODEL_NEHALEM_2E);
+}
+
+
+
+
+static INLINE Bool
+CPUID_FAMILY_IS_K7(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_K7;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_K8(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_K8;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_K8EXT(uint32 eax)
+{
+   /*
+    * We check for this pattern often enough that it's
+    * worth a separate function, for syntactic sugar.
+    */
+   return CPUID_FAMILY_IS_K8(eax) &&
+          CPUID_EXTENDED_MODEL(eax) != 0;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_K8L(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_K8L ||
+          CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_LLANO;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_K8MOBILE(uint32 eax)
+{
+   /* Essentially a K8 (not K8L) part, but with mobile features. */
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_K8MOBILE;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_K8STAR(uint32 eax)
+{
+   /*
+    * Read function name as "K8*", as in wildcard.
+    * Matches K8 or K8L or K8MOBILE
+    */
+   return CPUID_FAMILY_IS_K8(eax) || CPUID_FAMILY_IS_K8L(eax) ||
+          CPUID_FAMILY_IS_K8MOBILE(eax);
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_BOBCAT(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_BOBCAT;
+}
+
+static INLINE Bool
+CPUID_FAMILY_IS_BULLDOZER(uint32 eax)
+{
+   return CPUID_EFFECTIVE_FAMILY(eax) == CPUID_FAMILY_BULLDOZER;
+}
+
+/*
+ * AMD Barcelona (of either Opteron or Phenom kind).
+ */
+static INLINE Bool
+CPUID_MODEL_IS_BARCELONA(uint32 v) // IN: %eax from CPUID with %eax=1.
+{
+   /* Assumes the CPU manufacturer is AMD. */
+   return CPUID_EFFECTIVE_FAMILY(v) == CPUID_FAMILY_K8L &&
+          CPUID_EFFECTIVE_MODEL(v)  == CPUID_MODEL_BARCELONA_02;
+}
+
+
+#define CPUID_TYPE_PRIMARY     0
+#define CPUID_TYPE_OVERDRIVE   1
+#define CPUID_TYPE_SECONDARY   2
+
+#define CPUID_INTEL_ID4EAX_CACHE_TYPE_NULL      0
+#define CPUID_INTEL_ID4EAX_CACHE_TYPE_DATA      1
+#define CPUID_INTEL_ID4EAX_CACHE_TYPE_INST      2
+#define CPUID_INTEL_ID4EAX_CACHE_TYPE_UNIF      3
+
+#define CPUID_INTEL_ID4EAX_CACHE_SELF_INIT      0x00000100
+#define CPUID_INTEL_ID4EAX_CACHE_FULLY_ASSOC    0x00000200
+
+#define CPUID_INTEL_IDBECX_LEVEL_TYPE_INVALID   0
+#define CPUID_INTEL_IDBECX_LEVEL_TYPE_SMT       1
+#define CPUID_INTEL_IDBECX_LEVEL_TYPE_CORE      2
+
+
+/*
+ * For certain AMD processors, an lfence instruction is necessary at various
+ * places to ensure ordering.
+ */
+
+static INLINE Bool
+CPUID_VendorRequiresFence(CpuidVendor vendor)
+{
+   return vendor == CPUID_VENDOR_AMD;
+}
+
+static INLINE Bool
+CPUID_VersionRequiresFence(uint32 version)
+{
+   return CPUID_EFFECTIVE_FAMILY(version) == CPUID_FAMILY_K8 &&
+          CPUID_EFFECTIVE_MODEL(version) < 0x40;
+}
+
+static INLINE Bool
+CPUID_ID0RequiresFence(CPUIDRegs *id0)
+{
+   if (id0->eax == 0) {
+      return FALSE;
+   }
+   return CPUID_IsVendorAMD(id0);
+}
+
+static INLINE Bool
+CPUID_ID1RequiresFence(CPUIDRegs *id1)
+{
+   return CPUID_VersionRequiresFence(id1->eax);
+}
+
+static INLINE Bool
+CPUID_RequiresFence(CpuidVendor vendor, // IN
+                    uint32 version)      // IN: %eax from CPUID with %eax=1.
+{
+   return CPUID_VendorRequiresFence(vendor) &&
+	  CPUID_VersionRequiresFence(version);
+}
+
+
+/*
+ * The following low-level functions compute the number of
+ * cores per cpu.  They should be used cautiously because
+ * they do not necessarily work on all types of CPUs.
+ * High-level functions that are correct for all CPUs are
+ * available elsewhere: see lib/cpuidInfo/cpuidInfo.c.
+ */
+
+static INLINE uint32
+CPUID_IntelCoresPerPackage(uint32 v) /* %eax from CPUID with %eax=4 and %ecx=0. */
+{
+   // Note: This is not guaranteed to work on older Intel CPUs.
+   return 1 + CPUID_INTEL_CORE_COUNT(v);
+}
+
+
+static INLINE uint32
+CPUID_AMDCoresPerPackage(uint32 v) /* %ecx from CPUID with %eax=0x80000008. */
+{
+   // Note: This is not guaranteed to work on older AMD CPUs.
+   return 1 + CPUID_AMD_CORE_COUNT(v);
+}
+
+
+/*
+ * Hypervisor CPUID space is 0x400000XX.
+ */
+static INLINE Bool
+CPUID_IsHypervisorLevel(uint32 level)
+{
+   return (level & 0xffffff00) == 0x40000000;
+}
+
+
+#endif
diff --git a/sys/dev/virtual/vmware/shared/x86cpuid_asm.h b/sys/dev/virtual/vmware/shared/x86cpuid_asm.h
new file mode 100644
index 0000000..5aaedae
--- /dev/null
+++ b/sys/dev/virtual/vmware/shared/x86cpuid_asm.h
@@ -0,0 +1,463 @@
+/*********************************************************
+ * Copyright (C) 2003-2009 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * 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(unsigned int*, unsigned int);
+#pragma intrinsic(__cpuid)
+#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((unsigned 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
+
+/*
+ * No inline assembly in Win64. Implemented in bora/lib/user in
+ * cpuidMasm64.asm.
+ */
+
+extern void
+__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs);
+
+#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((unsigned 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((unsigned 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((unsigned 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((unsigned 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/user 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))
+
+static INLINE void
+__GET_CPUID4(int inputEcx, CPUIDRegs *regs)
+{
+   __GET_CPUID2(4, inputEcx, regs);
+}
+
+/* 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;                      \
+}
+
+
+#endif
diff --git a/sys/dev/virtual/vmware/vmblock/COPYING b/sys/dev/virtual/vmware/vmblock/COPYING
new file mode 100644
index 0000000..f92946e
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/COPYING
@@ -0,0 +1,24 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of VMware Inc. nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission of VMware Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/sys/dev/virtual/vmware/vmblock/Makefile b/sys/dev/virtual/vmware/vmblock/Makefile
new file mode 100644
index 0000000..bba697d
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/Makefile
@@ -0,0 +1,8 @@
+KMOD=	vmblock
+
+SRCS=	block.c os_panic.c vfsops.c vnops.c subr.c stubs.c
+SRCS+=	block.h vmblock_k.h os.h
+
+CFLAGS+=-I${.CURDIR}/../shared
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/virtual/vmware/vmblock/block.c b/sys/dev/virtual/vmware/vmblock/block.c
new file mode 100644
index 0000000..5e3c7b7
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/block.c
@@ -0,0 +1,632 @@
+/*********************************************************
+ * Copyright (C) 2006 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * block.c --
+ *
+ *      Blocking operation implementions for the vmblock driver.
+ */
+
+/* os.h includes necessary OS-specific headers. */
+#include "os.h"
+
+#if defined(vmblock_fuse)
+#elif defined(linux)
+# include "vmblockInt.h"
+#elif defined(sun)
+# include "module.h"
+#elif defined(__DragonFly__)
+# include "vmblock_k.h"
+#endif
+#include "block.h"
+#include "dbllnklst.h"
+
+typedef struct BlockInfo {
+   DblLnkLst_Links links;
+   os_atomic_t refcount;
+   os_blocker_id_t blocker;
+   os_completion_t completion;
+   char filename[OS_PATH_MAX];
+} BlockInfo;
+
+
+/* XXX: Is it worth turning this into a hash table? */
+static DblLnkLst_Links blockedFiles;
+static os_rwlock_t blockedFilesLock;
+static os_kmem_cache_t *blockInfoCache = NULL;
+
+/* Utility functions */
+static Bool BlockExists(const char *filename);
+static BlockInfo *GetBlock(const char *filename, const os_blocker_id_t blocker);
+static BlockInfo *AllocBlock(os_kmem_cache_t *cache,
+                             const char *filename, const os_blocker_id_t blocker);
+static void FreeBlock(os_kmem_cache_t *cache, BlockInfo *block);
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockInit --
+ *
+ *    Initializes blocking portion of module.
+ *
+ * Results:
+ *    Zero on success, error code on failure.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+BlockInit(void)
+{
+   ASSERT(!blockInfoCache);
+
+#if 0 /* XXX swildner: we take kmalloc()/kfree() for now */
+   blockInfoCache = os_kmem_cache_create("blockInfoCache",
+                                         sizeof (BlockInfo),
+                                         0,
+                                         NULL);
+   if (!blockInfoCache) {
+      return OS_ENOMEM;
+   }
+#endif
+
+   DblLnkLst_Init(&blockedFiles);
+   os_rwlock_init(&blockedFilesLock);
+
+   return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockCleanup --
+ *
+ *    Cleans up the blocking portion of the module.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+BlockCleanup(void)
+{
+   ASSERT(blockInfoCache);
+   ASSERT(!DblLnkLst_IsLinked(&blockedFiles));
+
+   os_rwlock_destroy(&blockedFilesLock);
+#if 0 /* XXX swildner: take kmalloc()/kfree() for now */
+   os_kmem_cache_destroy(blockInfoCache);
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockAddFileBlock --
+ *
+ *    Adds a block for the provided filename.  filename should be the name of
+ *    the actual file being blocked, not the name within our namespace.  The
+ *    provided blocker ID should uniquely identify this blocker.
+ *
+ *    All calls to BlockWaitOnFile() with the same filename will not return
+ *    until BlockRemoveFileBlock() is called.
+ *
+ *    Note that this function assumes a block on filename does not already
+ *    exist.
+ *
+ * Results:
+ *    Zero on success, error code on failure.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+BlockAddFileBlock(const char *filename,           // IN: name of file to block
+                  const os_blocker_id_t blocker)  // IN: blocker adding the block
+{
+   BlockInfo *block;
+
+   ASSERT(filename);
+
+   /* Create a new block. */
+   block = AllocBlock(blockInfoCache, filename, blocker);
+   if (!block) {
+      Warning("BlockAddFileBlock: out of memory\n");
+      return OS_ENOMEM;
+   }
+   os_write_lock(&blockedFilesLock);
+
+   /*
+    * Prevent duplicate blocks of any filename.  Done under same lock as list
+    * addition to ensure check for and adding of file are atomic.
+    */
+   if (BlockExists(filename)) {
+      Warning("BlockAddFileBlock: block already exists for [%s]\n", filename);
+      os_write_unlock(&blockedFilesLock);
+      FreeBlock(blockInfoCache, block);
+      return OS_EEXIST;
+   }
+
+   DblLnkLst_LinkLast(&blockedFiles, &block->links);
+
+   os_write_unlock(&blockedFilesLock);
+
+   LOG(4, "added block for [%s]\n", filename);
+
+   return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockRemoveFileBlock --
+ *
+ *    Removes the provided file block and wakes up any threads waiting within
+ *    BlockWaitOnFile().  Note that only the blocker that added a block can
+ *    remove it.
+ *
+ * Results:
+ *    Zero on success, error code on failure.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+BlockRemoveFileBlock(const char *filename,          // IN: block to remove
+                     const os_blocker_id_t blocker) // IN: blocker removing this block
+{
+   BlockInfo *block;
+
+   ASSERT(filename);
+
+   os_write_lock(&blockedFilesLock);
+
+   block = GetBlock(filename, blocker);
+   if (!block) {
+      os_write_unlock(&blockedFilesLock);
+      return OS_ENOENT;
+   }
+
+   DblLnkLst_Unlink1(&block->links);
+   os_write_unlock(&blockedFilesLock);
+
+   /* Undo GetBlock's refcount increment first. */
+   os_atomic_dec(&block->refcount);
+
+   /*
+    * Now remove /our/ reference.  (As opposed to references by waiting
+    * threads.)
+    */
+   if (os_atomic_dec_and_test(&block->refcount)) {
+      /* No threads are waiting, so clean up ourself. */
+      LOG(4, "Freeing block with no waiters on [%s]\n", filename);
+      FreeBlock(blockInfoCache, block);
+   } else {
+      /* Wake up waiters; the last one will free the BlockInfo */
+      LOG(4, "Completing block on [%s]\n", filename);
+      os_complete_all(&block->completion);
+   }
+
+   return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockRemoveAllBlocks --
+ *
+ *    Removes all blocks added by the provided blocker.
+ *
+ * Results:
+ *    Returns the number of entries removed from the blocklist.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned int
+BlockRemoveAllBlocks(const os_blocker_id_t blocker)  // IN: blocker to remove blocks for
+{
+   struct DblLnkLst_Links *curr;
+   struct DblLnkLst_Links *tmp;
+   unsigned int removed = 0;
+
+   os_write_lock(&blockedFilesLock);
+
+   DblLnkLst_ForEachSafe(curr, tmp, &blockedFiles) {
+      BlockInfo *currBlock = DblLnkLst_Container(curr, BlockInfo, links);
+      if (currBlock->blocker == blocker || blocker == OS_UNKNOWN_BLOCKER) {
+
+         DblLnkLst_Unlink1(&currBlock->links);
+
+         /*
+          * We count only entries removed from the -list-, regardless of whether
+          * or not other waiters exist.
+          */
+         ++removed;
+
+         /*
+          * BlockInfos, as the result of placing a block on a file or directory,
+          * reference themselves.  When the block is lifted, we need to remove
+          * this self-reference and handle the result appropriately.
+          */
+         if (os_atomic_dec_and_test(&currBlock->refcount)) {
+            /* Free blocks without any waiters ... */
+            LOG(4, "Freeing block with no waiters for blocker [%p] (%s)\n",
+                blocker, currBlock->filename);
+            FreeBlock(blockInfoCache, currBlock);
+         } else {
+            /* ... or wakeup the waiting threads */
+            LOG(4, "Completing block for blocker [%p] (%s)\n",
+                blocker, currBlock->filename);
+            os_complete_all(&currBlock->completion);
+         }
+      }
+   }
+
+   os_write_unlock(&blockedFilesLock);
+
+   return removed;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockWaitOnFile --
+ *
+ *    Searches for a block on the provided filename.  If one exists, this
+ *    function does not return until that block has been lifted; otherwise, it
+ *    returns right away.
+ *
+ * Results:
+ *    Zero on success, otherwise an appropriate system error if our sleep/
+ *    block is interrupted.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+BlockWaitOnFile(const char *filename,   // IN: file to block on
+                BlockHandle cookie)     // IN: previously found block
+{
+   BlockInfo *block = NULL;
+   int error = 0;
+
+   ASSERT(filename);
+
+   /*
+    * Caller may have used BlockLookup to conditionally search for a
+    * block before actually going to sleep.  (This allows the caller to
+    * do a little housekeeping, such as releasing vnode locks, before
+    * blocking here.)
+    */
+   if (cookie == NULL) {
+      os_read_lock(&blockedFilesLock);
+      block = GetBlock(filename, OS_UNKNOWN_BLOCKER);
+      os_read_unlock(&blockedFilesLock);
+
+      if (!block) {
+         /* This file is not blocked, just return */
+         return 0;
+      }
+   } else {
+      /*
+       * Note that the "cookie's" reference count was incremented when it
+       * was fetched via BlockLookup, so this is completely safe.  (We'll
+       * decrement it below.)
+       */
+      block = cookie;
+   }
+
+   LOG(4, "(%"OS_FMTTID") Waiting for completion on [%s]\n", os_threadid, filename);
+   error = os_wait_for_completion(&block->completion);
+   LOG(4, "(%"OS_FMTTID") Wokeup from block on [%s]\n", os_threadid, filename);
+
+   /*
+    * The assumptions here are as follows:
+    *   1.  The BlockInfo holds a reference to itself.  (BlockInfo's refcount
+    *       is initialized to 1.)
+    *   2.  BlockInfo's self reference is deleted only when BlockInfo is
+    *       /also/ removed removed from the block list.
+    *
+    * Therefore, if the reference count hits zero, it's because the block is
+    * no longer in the list, and there is no chance of another thread finding
+    * and referencing this block between our dec_and_test and freeing it.
+    */
+   if (os_atomic_dec_and_test(&block->refcount)) {
+      /* We were the last thread, so clean up */
+      LOG(4, "(%"OS_FMTTID") I am the last to wakeup, freeing the block on [%s]\n",
+          os_threadid, filename);
+      FreeBlock(blockInfoCache, block);
+   }
+
+   return error;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * BlockLookup --
+ *
+ *      VFS-exported function for searching for blocks.
+ *
+ * Results:
+ *      Opaque pointer to a blockInfo if a block is found, NULL otherwise.
+ *
+ * Side effects:
+ *      Located blockInfo, if any, has an incremented reference count.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+BlockHandle
+BlockLookup(const char *filename,               // IN: pathname to test for
+                                                //     blocking
+            const os_blocker_id_t blocker)      // IN: specific blocker to
+                                                //     search for
+{
+   BlockInfo *block;
+
+   os_read_lock(&blockedFilesLock);
+
+   block = GetBlock(filename, blocker);
+
+   os_read_unlock(&blockedFilesLock);
+
+   return block;
+}
+
+
+#ifdef VMX86_DEVEL
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockListFileBlocks --
+ *
+ *    Lists all the current file blocks.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+BlockListFileBlocks(void)
+{
+   DblLnkLst_Links *curr;
+   int count = 0;
+
+   os_read_lock(&blockedFilesLock);
+
+   DblLnkLst_ForEach(curr, &blockedFiles) {
+      BlockInfo *currBlock = DblLnkLst_Container(curr, BlockInfo, links);
+      LOG(1, "BlockListFileBlocks: (%d) Filename: [%s], Blocker: [%p]\n",
+          count++, currBlock->filename, currBlock->blocker);
+   }
+
+   os_read_unlock(&blockedFilesLock);
+
+   if (!count) {
+      LOG(1, "BlockListFileBlocks: No blocks currently exist.\n");
+   }
+}
+#endif
+
+
+/* Utility functions */
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * BlockExists --
+ *
+ *    Checks if a block already exists for the provided filename.
+ *
+ *    Note that this assumes the proper locking has been done on the data
+ *    structure holding the blocked files (including ensuring the atomic_dec()
+ *    without a kmem_cache_free() is safe).
+ *
+ * Results:
+ *    TRUE if a block exists, FALSE otherwise.
+ *
+ * Side effects:
+ *    If a block exists, its refcount is incremented and decremented.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static Bool
+BlockExists(const char *filename)
+{
+   BlockInfo *block = GetBlock(filename, OS_UNKNOWN_BLOCKER);
+
+   if (block) {
+      os_atomic_dec(&block->refcount);
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * GetBlock --
+ *
+ *    Searches for a block on the provided filename by the provided blocker.
+ *    If blocker is NULL, it is ignored and any matching filename is returned.
+ *    If a block is found, the refcount is incremented.
+ *
+ *    Note that this assumes the proper locking has been done on the data
+ *    structure holding the blocked files.
+ *
+ * Results:
+ *    A pointer to the corresponding BlockInfo if found, NULL otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static BlockInfo *
+GetBlock(const char *filename,          // IN: file to find block for
+         const os_blocker_id_t blocker) // IN: blocker associated with this block
+{
+   struct DblLnkLst_Links *curr;
+
+   /*
+    * On FreeBSD we have a mechanism to assert (but not simply check)
+    * that a lock is held. Since semantic is different (panic that
+    * happens if assertion fails can not be suppressed) we are using
+    * different name.
+    */
+#ifdef os_assert_rwlock_held
+   os_assert_rwlock_held(&blockedFilesLock);
+#else
+   ASSERT(os_rwlock_held(&blockedFilesLock));
+#endif
+
+   DblLnkLst_ForEach(curr, &blockedFiles) {
+      BlockInfo *currBlock = DblLnkLst_Container(curr, BlockInfo, links);
+      if ((blocker == OS_UNKNOWN_BLOCKER || currBlock->blocker == blocker) &&
+          strcmp(currBlock->filename, filename) == 0) {
+         os_atomic_inc(&currBlock->refcount);
+         return currBlock;
+      }
+   }
+
+   return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AllocBlock --
+ *
+ *    Allocates and initializes a new block structure.
+ *
+ * Results:
+ *    Pointer to the struct on success, NULL on failure.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BlockInfo *
+AllocBlock(os_kmem_cache_t *cache,        // IN: cache to allocate from
+           const char *filename,          // IN: filname of block
+           const os_blocker_id_t blocker) // IN: blocker id
+{
+   BlockInfo *block;
+   size_t ret;
+
+   /* Initialize this file's block structure. */
+   block = os_kmem_cache_alloc(blockInfoCache);
+   if (!block) {
+      return NULL;
+   }
+
+   ret = strlcpy(block->filename, filename, sizeof block->filename);
+   if (ret >= sizeof block->filename) {
+      Warning("BlockAddFileBlock: filename is too large\n");
+      os_kmem_cache_free(blockInfoCache, block);
+      return NULL;
+   }
+
+   DblLnkLst_Init(&block->links);
+   os_atomic_set(&block->refcount, 1);
+   os_completion_init(&block->completion);
+   block->blocker = blocker;
+
+   return block;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * FreeBlock --
+ *
+ *    Frees the provided block structure.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+FreeBlock(os_kmem_cache_t *cache,       // IN: cache block was allocated from
+          BlockInfo *block)             // IN: block to free
+{
+   ASSERT(cache);
+   ASSERT(block);
+
+   os_completion_destroy(&block->completion);
+   os_kmem_cache_free(cache, block);
+}
diff --git a/sys/dev/virtual/vmware/vmblock/block.h b/sys/dev/virtual/vmware/vmblock/block.h
new file mode 100644
index 0000000..f79618b
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/block.h
@@ -0,0 +1,59 @@
+/*********************************************************
+ * Copyright (C) 2006 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * block.h --
+ *
+ *   Blocking operations for the vmblock driver.
+ */
+
+#ifndef __BLOCK_H__
+#define __BLOCK_H__
+
+#include "os.h"
+
+typedef struct BlockInfo * BlockHandle;
+
+/*
+ * Global functions
+ */
+
+int BlockInit(void);
+void BlockCleanup(void);
+int BlockAddFileBlock(const char *filename, const os_blocker_id_t blocker);
+int BlockRemoveFileBlock(const char *filename, const os_blocker_id_t blocker);
+unsigned int BlockRemoveAllBlocks(const os_blocker_id_t blocker);
+int BlockWaitOnFile(const char *filename, BlockHandle cookie);
+BlockHandle BlockLookup(const char *filename, const os_blocker_id_t blocker);
+#ifdef VMX86_DEVEL
+void BlockListFileBlocks(void);
+#endif
+
+#endif /* __BLOCK_H__ */
diff --git a/sys/dev/virtual/vmware/vmblock/dbllnklst.c b/sys/dev/virtual/vmware/vmblock/dbllnklst.c
new file mode 100644
index 0000000..c7a1723
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/dbllnklst.c
@@ -0,0 +1,210 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+#include "vmware.h"
+#include "dbllnklst.h"
+
+/*
+ * dbllnklst.c --
+ *
+ *    Light (but nonetheless powerful) implementation of doubly linked lists
+ */
+
+
+/*
+ * XXX This file is empty because I made all the functions inline.
+ * -- edward
+ */
+
+
+#if 0
+/*
+ * Test code (which also demonstrates how to use this library)
+ */
+
+/*
+ * Add the double linked list capability to any of your data structure just by
+ * adding a DblLnkLst_Links field inside it. It is not required that the field
+ * comes first, but if it does, the execution will be slighly faster.
+ *
+ * Here we create a doubly linked list of integers
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef struct member {
+   int i;
+   DblLnkLst_Links l;
+} member;
+
+
+/* Member constructor */
+member *
+make_member(int i)
+{
+   member *m;
+
+   m = malloc(sizeof(*m));
+   DblLnkLst_Init(&m->l);
+   m->i = i;
+
+   return m;
+}
+
+
+/* Dump a circular list */
+void
+dump_circular(const member *c) // IN
+{
+   const member *current;
+
+   printf("forward: ");
+   current = c;
+   do {
+      printf("%d ", current->i);
+      current = DblLnkLst_Container(current->l.next, member, l);
+   } while (current != c);
+   printf("backward: ");
+   do {
+      printf("%d ", current->i);
+      current = DblLnkLst_Container(current->l.prev, member, l);
+   } while (current != c);
+   printf("\n");
+}
+
+
+/* Dump an anchored list */
+void
+dump_anchored(const DblLnkLst_Links *h) // IN
+{
+   DblLnkLst_Links *cur_l;
+
+   printf("forward: ");
+   for (cur_l = h->next; cur_l != h; cur_l = cur_l->next) {
+      member *current;
+
+      current = DblLnkLst_Container(cur_l, member, l);
+      printf("%d ", current->i);
+   }
+   printf("backward: ");
+   for (cur_l = h->prev; cur_l != h; cur_l = cur_l->prev) {
+      member *current;
+
+      current = DblLnkLst_Container(cur_l, member, l);
+      printf("%d ", current->i);
+   }
+   printf("\n");
+}
+
+
+/* Test code entry point */
+int
+main(int argc,    // IN
+     char **argv) // IN
+{
+   member *c1;
+   member *c2;
+   member *c3;
+   member *c4;
+
+   DblLnkLst_Links h;
+   member *a1;
+   member *a2;
+   member *a3;
+
+   printf("Circular list: there is no origin\n");
+
+   /* Create the 1st member */
+   c1 = make_member(1);
+   /* Special case: there is no list to merge with, initially */
+
+   /* Add the 2nd member _after_ the 1st one */
+   c2 = make_member(2);
+   DblLnkLst_Link(&c1->l, &c2->l);
+
+   /* Add the 3rd member _after_ the 2nd one */
+   c3 = make_member(3);
+   DblLnkLst_Link(&c1->l, &c3->l);
+
+   /* Add the 4th member _before_ the 3rd one */
+   c4 = make_member(4);
+   DblLnkLst_Link(&c3->l, &c4->l);
+
+   printf("See it from this member...\n");
+   dump_circular(c1);
+   printf("...Or from this one\n");
+   dump_circular(c4);
+
+   printf("\n");
+   printf("Anchored (linear) list: it has a beginning and an end\n");
+
+   /* Create the 'head' of the list */
+   DblLnkLst_Init(&h);
+
+   /* Add the 1st member at the _end_ */
+   a1 = make_member(5);
+   DblLnkLst_LinkLast(&h, &a1->l);
+
+   /* Add the 2nd member at the _beginning_ */
+   a2 = make_member(6);
+   DblLnkLst_LinkFirst(&h, &a2->l);
+
+   /* Add the 3rd member _before_ the 1st one */
+   a3 = make_member(7);
+   DblLnkLst_Link(&a1->l, &a3->l);
+
+   dump_anchored(&h);
+
+   printf("\n");
+   printf("Merge both lists: the result is an anchored list\n");
+
+   DblLnkLst_Link(&h, &c4->l);
+
+   dump_anchored(&h);
+
+   printf("\n");
+   printf("Remove a member\n");
+
+   DblLnkLst_Unlink1(&c3->l);
+
+   dump_anchored(&h);
+
+   printf("\n");
+   printf("Split the result in two lists: an anchored one and a circular "
+          "one\n");
+   DblLnkLst_Unlink(&h, &a1->l);
+
+   dump_anchored(&h);
+   dump_circular(a1);
+
+   return 0;
+}
+#endif
diff --git a/sys/dev/virtual/vmware/vmblock/os.h b/sys/dev/virtual/vmware/vmblock/os.h
new file mode 100644
index 0000000..03d2e7c
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/os.h
@@ -0,0 +1,132 @@
+/*********************************************************
+ * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+
+/*
+ * os.h --
+ *
+ *      FreeBSD-specific definitions.
+ */
+
+
+#ifndef __OS_H__
+#define __OS_H__
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <machine/stdarg.h>
+
+#include "vm_basic_types.h"
+
+typedef struct lock os_rwlock_t;
+
+typedef void os_kmem_cache_t;
+typedef struct os_completion_t {
+   Bool completed;
+   struct lock lock;
+   struct cv cv;
+} os_completion_t;
+/*
+ * Changing the os_atomic_t type requires that the os_atomic_* macros below be
+ * changed as well.
+ */
+typedef unsigned int os_atomic_t;
+typedef struct file * os_blocker_id_t;
+
+#define OS_UNKNOWN_BLOCKER              NULL
+#define OS_ENOMEM                       ENOMEM
+#define OS_ENOENT                       ENOENT
+#define OS_EEXIST                       EEXIST
+#define OS_PATH_MAX                     MAXPATHLEN
+#define OS_KMEM_CACHE_FLAG_HWALIGN      0       // unused
+
+#define OS_FMTTID                       "p"
+#define os_threadid                     curthread
+
+extern NORETURN void os_panic(const char *fmt, __va_list args);
+
+#define os_rwlock_init(lock)            lockinit(lock, "vmblock-sx", 0, LK_CANRECURSE)
+#define os_rwlock_destroy(lock)         lockuninit(lock)
+#define os_assert_rwlock_held(lock)     KKASSERT(lockstatus(lock, curthread))
+#define os_read_lock(lock)              lockmgr(lock, LK_SHARED)
+#define os_write_lock(lock)             lockmgr(lock, LK_EXCLUSIVE)
+#define os_read_unlock(lock)            lockmgr(lock, LK_RELEASE)
+#define os_write_unlock(lock)           lockmgr(lock, LK_RELEASE)
+
+MALLOC_DEFINE(M_VMBLOCKINFO, "vmblockinfo", "");
+
+#define os_kmem_cache_alloc(cache)      kmalloc(sizeof (BlockInfo), M_VMBLOCKINFO, M_WAITOK)
+#define os_kmem_cache_free(cache, elem) kfree(elem, M_VMBLOCKINFO)
+
+#define os_completion_init(comp)                                \
+      do {                                                      \
+         (comp)->completed = FALSE;                             \
+         lockinit(&(comp)->lock, "vmblock-lock", 0, LK_CANRECURSE); \
+         cv_init(&(comp)->cv, "vmblock-cv");                       \
+      } while (0)
+#define os_completion_destroy(comp)                             \
+      do {                                                      \
+         lockuninit(&(comp)->lock);                           \
+         cv_destroy(&(comp)->cv);                               \
+      } while (0)
+/*
+ * This macro evaluates to non-zero only if cv_wait_sig is interrupted.
+ */
+#define os_wait_for_completion(comp)                            \
+({                                                              \
+         int error = 0;                                         \
+         lockmgr(&(comp)->lock, LK_EXCLUSIVE);				\
+         while (!(comp)->completed && !error) {                 \
+            error = cv_wait_sig(&(comp)->cv, &(comp)->lock);   \
+         }                                                      \
+         lockmgr(&(comp)->lock, LK_RELEASE);				\
+         error;                                                 \
+})
+#define os_complete_all(comp)                                   \
+      do {                                                      \
+         lockmgr(&(comp)->lock, LK_EXCLUSIVE);				\
+         (comp)->completed = TRUE;                              \
+         cv_broadcast(&(comp)->cv);                             \
+         lockmgr(&(comp)->lock, LK_RELEASE);				\
+      } while (0)
+
+/* atomic_fetchadd_int returns the value of atomic before addition. */
+#define os_atomic_dec_and_test(atomic)  (atomic_fetchadd_int(atomic, -1) == 1)
+#define os_atomic_dec(atomic)           atomic_subtract_int(atomic, 1)
+#define os_atomic_inc(atomic)           atomic_add_int(atomic, 1)
+#define os_atomic_set(atomic, val)      atomic_store_rel_int(atomic, val)
+#define os_atomic_read(atomic)          atomic_load_acq_int(atomic)
+
+#endif /* __OS_H__ */
diff --git a/sys/dev/virtual/vmware/vmblock/os_panic.c b/sys/dev/virtual/vmware/vmblock/os_panic.c
new file mode 100644
index 0000000..952b06c
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/os_panic.c
@@ -0,0 +1,70 @@
+/*********************************************************
+ * Copyright (C) 2011 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+
+/*
+ * os_panic.c --
+ *
+ *     Vararg panic implementation for FreeBSD.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <machine/stdarg.h>
+
+#include "os.h"
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * os_panic --
+ *
+ *    FreeBSD panic implementation that takes va_list argument.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    We panic.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+os_panic(const char *fmt,  // IN
+         __va_list args)     // IN
+{
+   static char message[1024];
+
+   kvsnprintf(message, sizeof message - 1, fmt, args);
+   message[sizeof message - 1] = '\0';
+
+   panic("%s", message);
+}
diff --git a/sys/dev/virtual/vmware/vmblock/stubs.c b/sys/dev/virtual/vmware/vmblock/stubs.c
new file mode 100644
index 0000000..bed93b0
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/stubs.c
@@ -0,0 +1,79 @@
+/*********************************************************
+ * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+
+/*
+ * stubs.c --
+ *
+ *      Common stubs.
+ */
+
+#if defined(__DragonFly__)
+#include <sys/cdefs.h>
+#include <machine/stdarg.h>
+#else
+#include <stdarg.h>
+#endif
+
+#include "os.h"
+#include "vm_assert.h"
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * Panic --
+ *
+ *    Panic implementation.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+Panic(const char *fmt, ...)
+{
+   __va_list args;
+
+   __va_start(args, fmt);
+   os_panic(fmt, args);
+   __va_end(args);
+
+   /*
+    * Solaris's vcmn_err() is not marked as NORETURN and thus generates a
+    * warning. I'd use NOT_REACHED(), as recommended, except that we are
+    * already in Panic().
+    */
+   INFINITE_LOOP();
+}
diff --git a/sys/dev/virtual/vmware/vmblock/subr.c b/sys/dev/virtual/vmware/vmblock/subr.c
new file mode 100644
index 0000000..0025a2e
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/subr.c
@@ -0,0 +1,488 @@
+/* **********************************************************
+ * Copyright 2007 VMware, Inc.  All rights reserved.
+ * **********************************************************/
+
+/*
+ * subr.c --
+ *
+ *	Subroutines for the VMBlock filesystem on FreeBSD.
+ */
+
+
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software donated to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)null_subr.c	8.7 (Berkeley) 5/14/95
+ *
+ * $FreeBSD: src/sys/fs/nullfs/null_subr.c,v 1.48.2.1 2006/03/13 03:05:17 jeff Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/file.h>
+
+#include "compat_freebsd.h"
+
+#include "vmblock_k.h"
+#include "block.h"
+
+#define LOG2_SIZEVNODE  8		/* log2(sizeof struct vnode) */
+#define	NVMBLOCKCACHE   16              /* Number of hash buckets/chains */
+
+
+/*
+ * Local data
+ */
+
+/*
+ * VMBlock layer cache:
+ *    Each cache entry holds a reference to the lower vnode along with a
+ *    pointer to the alias vnode.  When an entry is added the lower vnode
+ *    is VREF'd.  When the alias is removed the lower vnode is vrele'd.
+ */
+
+#define	VMBLOCK_NHASH(vp) \
+	(&nodeHashTable[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & nodeHashMask])
+
+/*
+ * See hashinit(9).
+ */
+static LIST_HEAD(nodeHashHead, VMBlockNode) *nodeHashTable;
+static u_long nodeHashMask;
+static struct lock hashLock;
+
+static MALLOC_DEFINE(M_VMBLOCKFSHASH, "VMBlockFS hash", "VMBlockFS hash table");
+MALLOC_DEFINE(M_VMBLOCKFSNODE, "VMBlockFS node", "VMBlockFS vnode private part");
+
+/* Defined for quick access to temporary pathname buffers. */
+struct objcache *VMBlockPathnameZone;
+
+
+/*
+ * Local functions
+ */
+
+static struct vnode * VMBlockHashGet(struct mount *, struct vnode *);
+static struct vnode * VMBlockHashInsert(struct mount *, struct VMBlockNode *);
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockInit --
+ *
+ *      Initialize VMBlock file system.  Called when module first loaded into
+ *      the kernel.
+ *
+ * Results:
+ *      Zero.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Original comments:
+ *      Initialise cache headers
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+VMBlockInit(struct vfsconf *vfsp)       // ignored
+{
+   VMBLOCKDEBUG("VMBlockInit\n");      /* printed during system boot */
+   nodeHashTable = hashinit(NVMBLOCKCACHE, M_VMBLOCKFSHASH, &nodeHashMask);
+   lockinit(&hashLock, "vmblock-hs", 0, LK_CANRECURSE);
+   VMBlockPathnameZone = uma_zcreate("VMBlock", MAXPATHLEN, NULL, NULL, NULL,
+                                     NULL, UMA_ALIGN_PTR, 0);
+   VMBlockSetupFileOps();
+   BlockInit();
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockUninit --
+ *
+ *      Clean up when module is unloaded.
+ *
+ * Results:
+ *      Zero always.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+VMBlockUninit(struct vfsconf *vfsp)     // ignored
+{
+   lockuninit(&hashLock);
+   kfree(nodeHashTable, M_VMBLOCKFSHASH);
+   BlockCleanup();
+   uma_zdestroy(VMBlockPathnameZone);
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockHashGet --
+ *
+ *      "Return a VREF'ed alias for lower vnode if already exists, else 0.
+ *      Lower vnode should be locked on entry and will be left locked on exit."
+ *
+ * Results:
+ *      Pointer to upper layer/alias vnode if lowervp found, otherwise NULL.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static struct vnode *
+VMBlockHashGet(struct mount *mp,        // IN: vmblock file system information
+               struct vnode *lowervp)   // IN: lower vnode to search for
+{
+   struct nodeHashHead *hd;
+   struct VMBlockNode *a;
+   struct vnode *vp;
+
+   ASSERT_VOP_LOCKED(lowervp, "hashEntryget");
+
+   /*
+    * Find hash base, and then search the (two-way) linked list looking
+    * for a VMBlockNode structure which is referencing the lower vnode.
+    * If found, the increment the VMBlockNode reference count (but NOT the
+    * lower vnode's VREF counter).
+    */
+   hd = VMBLOCK_NHASH(lowervp);
+   lockmgr(&hashLock, LK_EXCLUSIVE);
+   LIST_FOREACH(a, hd, hashEntry) {
+      if (a->lowerVnode == lowervp && VMBTOVP(a)->v_mount == mp) {
+         /*
+          * Since we have the lower node locked the nullfs node can not be
+          * in the process of recycling.  If it had been recycled before we
+          * grabed the lower lock it would not have been found on the hash.
+          */
+         vp = VMBTOVP(a);
+         vref(vp);
+         lockmgr(&hashLock, LK_RELEASE);
+         return vp;
+      }
+   }
+   lockmgr(&hashLock, LK_RELEASE);
+   return NULLVP;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockHashInsert --
+ *
+ *      "Act like VMBlockHashGet, but add passed VMBlockNode to hash if no
+ *      existing node found."
+ *
+ * Results:
+ *      Referenced, locked alias vnode if entry already in hash.  Otherwise
+ *      NULLVP.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static struct vnode *
+VMBlockHashInsert(struct mount *mp,             // IN: VMBlock file system info
+                  struct VMBlockNode *xp)       // IN: node to insert into hash
+{
+   struct nodeHashHead *hd;
+   struct VMBlockNode *oxp;
+   struct vnode *ovp;
+
+   hd = VMBLOCK_NHASH(xp->lowerVnode);
+   lockmgr(&hashLock, LK_EXCLUSIVE);
+   LIST_FOREACH(oxp, hd, hashEntry) {
+      if (oxp->lowerVnode == xp->lowerVnode && VMBTOVP(oxp)->v_mount == mp) {
+         /*
+          * See hashEntryget for a description of this
+          * operation.
+          */
+         ovp = VMBTOVP(oxp);
+         vref(ovp);
+         lockmgr(&hashLock, LK_RELEASE);
+         return ovp;
+      }
+   }
+   LIST_INSERT_HEAD(hd, xp, hashEntry);
+   lockmgr(&hashLock, LK_RELEASE);
+   return NULLVP;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockHashRem --
+ *
+ *      Remove a VMBlockNode from the hash.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+VMBlockHashRem(struct VMBlockNode *xp)  // IN: node to remove
+{
+   lockmgr(&hashLock, LK_EXCLUSIVE);
+   LIST_REMOVE(xp, hashEntry);
+   lockmgr(&hashLock, LK_RELEASE);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockInsMntQueDtr --
+ *
+ *      Do filesystem specific cleanup when recycling a vnode on a failed
+ *      insmntque1 call.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+VMBlockInsMntQueDtr(struct vnode *vp, // IN: node to cleanup
+		    void *xp)         // IN: FS private data
+{
+   vp->v_data = NULL;
+   vp->v_vnlock = &vp->v_lock;
+   kfree(xp, M_VMBLOCKFSNODE);
+   vp->v_op = &dead_vnodeops;
+   (void) compat_vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+   vgone(vp);
+   vput(vp);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockNodeGet --
+ *
+ *      Return a VMBlockNode mapped to the given lower layer vnode.
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      In case of success takes over ownership of pathname thus caller
+ *      has to dispose of it only if error was signalled.
+ *
+ * Original function comment:
+ *
+ *	Make a new or get existing nullfs node.  Vp is the alias vnode,
+ *	lowervp is the lower vnode.
+ *
+ *	The lowervp assumed to be locked and having "spare" reference. This
+ *	routine vrele lowervp if nullfs node was taken from hash. Otherwise it
+ *	"transfers" the caller's "spare" reference to created nullfs vnode.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+VMBlockNodeGet(struct mount *mp,        // IN: VMBlock fs info
+               struct vnode *lowervp,   // IN: lower layer vnode
+               struct vnode **vpp,      // OUT: upper layer/alias vnode
+               char         *pathname)  // IN: Pointer to the path we took to
+                                        //     reach this vnode
+{
+   struct VMBlockNode *xp;
+   struct vnode *vp;
+   int error;
+
+   /* Lookup the hash firstly */
+   *vpp = VMBlockHashGet(mp, lowervp);
+   if (*vpp != NULL) {
+      vrele(lowervp);
+      return 0;
+   }
+
+   /*
+    * We do not serialize vnode creation, instead we will check for duplicates
+    * later, when adding new vnode to hash.
+    *
+    * Note that duplicate can only appear in hash if the lowervp is locked
+    * LK_SHARED.
+    */
+
+   /*
+    * Do the malloc before the getnewvnode since doing so afterward might
+    * cause a bogus v_data pointer to get dereferenced elsewhere if malloc
+    * should block.
+    */
+   xp = kmalloc(sizeof *xp, M_VMBLOCKFSNODE, M_WAITOK|M_ZERO);
+
+   error = getnewvnode("vmblock", mp, &VMBlockVnodeOps, &vp);
+   if (error) {
+      kfree(xp, M_VMBLOCKFSNODE);
+      return error;
+   }
+
+   xp->name = pathname;
+   xp->backVnode = vp;
+   xp->lowerVnode = lowervp;
+   vp->v_type = lowervp->v_type;
+   vp->v_data = xp;
+   vp->v_vnlock = lowervp->v_vnlock;
+   if (vp->v_vnlock == NULL) {
+      panic("VMBlockNodeGet: Passed a NULL vnlock.\n");
+   }
+
+   /* Before FreeBSD 7, insmntque was called by getnewvnode. */
+#ifdef __DragonFly__
+   error = insmntque1(vp, mp, VMBlockInsMntQueDtr, xp);
+   if (error != 0) {
+      return error;
+   }
+#endif
+
+   /*
+    * Atomically insert our new node into the hash or vget existing if
+    * someone else has beaten us to it.
+    *
+    * ETA:  If a hash entry already exists, we'll be stuck with an orphaned
+    * vnode and associated VMBlockNode.  By vrele'ng this vp, it'll be reclaimed
+    * by the OS later.  That same process will take care of freeing the
+    * VMBlockNode, too.
+    */
+   *vpp = VMBlockHashInsert(mp, xp);
+   if (*vpp != NULL) {
+      vrele(lowervp);
+      vp->v_vnlock = &vp->v_lock;
+      xp->lowerVnode = NULL;
+      vrele(vp);
+   } else {
+      *vpp = vp;
+   }
+
+   return 0;
+}
+
+
+#ifdef DIAGNOSTIC                               /* if (DIAGNOSTIC) { */
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockCheckVp --
+ *
+ *      Sanity-checking intermediary used for debugging.  When module is
+ *      compiled with FreeBSD macro "DIAGNOSTIC", every instance of
+ *      VMBVPTOLOWERVP() calls this function to test vnodes' and VMBlockNodes'
+ *      values, printing diagnostic information before panicing.  If the kernel
+ *      debugger (KDB) is enabled, then this function will break to the debugger
+ *      before a panic.
+ *
+ * Results:
+ *      Valid pointer to a VMBlockNode's lower vnode.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+struct vnode *
+VMBlockCheckVp(struct vnode *vp, char *fil, int lno)
+{
+   struct VMBlockNode *a = VPTOVMB(vp);
+#ifdef notyet
+   /*
+    * Can't do this check because vop_reclaim runs
+    * with a funny vop vector.
+    */
+   if (vp->v_op != null_vnodeop_p) {
+      kprintf ("VMBlockCheckVp: on non-null-node\n");
+      panic("VMBlockCheckVp");
+   };
+#endif
+   if (a->lowerVnode == NULLVP) {
+      /* Should never happen */
+      int i; u_long *p;
+      kprintf("vp = %p, ZERO ptr\n", (void *)vp);
+      for (p = (u_long *) a, i = 0; i < 8; i++) {
+         kprintf(" %lx", p[i]);
+      }
+      kprintf("\n");
+      panic("VMBlockCheckVp");
+   }
+   if (vrefcnt(a->lowerVnode) < 1) {
+      int i; u_long *p;
+      kprintf("vp = %p, unref'ed lowervp\n", (void *)vp);
+      for (p = (u_long *) a, i = 0; i < 8; i++) {
+         kprintf(" %lx", p[i]);
+      }
+      kprintf("\n");
+      panic ("null with unref'ed lowervp");
+   };
+#ifdef notyet
+   kprintf("null %x/%d -> %x/%d [%s, %d]\n", VMBTOVP(a), vrefcnt(VMBTOVP(a)),
+      a->lowerVnode, vrefcnt(a->lowerVnode), fil, lno);
+#endif
+   return a->lowerVnode;
+}
+#endif                                          /* } [DIAGNOSTIC] */
diff --git a/sys/dev/virtual/vmware/vmblock/vfsops.c b/sys/dev/virtual/vmware/vmblock/vfsops.c
new file mode 100644
index 0000000..05eb52d
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/vfsops.c
@@ -0,0 +1,497 @@
+/* **********************************************************
+ * Copyright 2007 VMware, Inc.  All rights reserved.
+ * **********************************************************/
+
+/*
+ * vfsops.c --
+ *
+ *      VFS operations for VMBlock file system on FreeBSD.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software donated to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)null_vfsops.c	8.2 (Berkeley) 1/21/94
+ *
+ * @(#)lofs_vfsops.c	1.2 (Berkeley) 6/18/92
+ * $FreeBSD: src/sys/fs/nullfs/null_vfsops.c,v 1.72.2.5 2006/10/09 19:47:14 tegge Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/fcntl.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+
+#include "vmblock_k.h"
+#include "compat_freebsd.h"
+
+static MALLOC_DEFINE(M_VMBLOCKFSMNT, "VMBlockFS mount", "VMBlockFS mount structure");
+
+
+/*
+ * Local data
+ */
+
+static vfs_mount_t	VMBlockVFSMount;
+static vfs_root_t	VMBlockVFSRoot;
+static vfs_sync_t	VMBlockVFSSync;
+static vfs_statfs_t	VMBlockVFSStatFS;
+static vfs_unmount_t	VMBlockVFSUnmount;
+static vfs_vget_t	VMBlockVFSVGet;
+
+/*
+ * VFS operations vector
+ */
+static struct vfsops VMBlockVFSOps = {
+   .vfs_init            = VMBlockInit,
+   .vfs_uninit          = VMBlockUninit,
+   .vfs_mount           = VMBlockVFSMount,
+   .vfs_root            = VMBlockVFSRoot,
+   .vfs_statfs          = VMBlockVFSStatFS,
+   .vfs_sync            = VMBlockVFSSync,
+   .vfs_unmount         = VMBlockVFSUnmount,
+   .vfs_vget            = VMBlockVFSVGet,
+};
+
+/*
+ * The following generates a struct vfsconf for our filesystem & grafts us into
+ * the kernel's list of known filesystems at module load.
+ */
+VFS_SET(VMBlockVFSOps, vmblock, VFCF_LOOPBACK);
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVFSMount --
+ *
+ *      Mount the vmblock file system.
+ *
+ * Results:
+ *      Zero on success, otherwise an appropriate system error.  (See
+ *      VFS_MOUNT(9).)
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+#ifdef __DragonFly__
+VMBlockVFSMount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
+#else
+VMBlockVFSMount(struct mount *mp,        // IN: mount(2) parameters
+                struct thread *td)       // IN: caller's thread context
+#endif
+{
+   struct VMBlockMount *xmp;
+#if 0 /* XXX swildner */
+   struct nameidata nd, *ndp = &nd;
+#endif
+   struct vnode *lowerrootvp, *vp;
+   char *target;
+   char *pathname;
+   int len, error = 0;
+
+   VMBLOCKDEBUG("VMBlockVFSMount(mp = %p)\n", (void *)mp);
+
+   /*
+    * TODO:  Strip out extraneous export & other misc cruft.
+    */
+
+   /*
+    * Disallow the following:
+    *   1.  Mounting over the system root.
+    *   2.  Mount updates/remounts.  (Reconsider for rw->ro, ro->rw?)
+    *   3.  Mounting VMBlock on top of a VMBlock.
+    */
+   if ((mp->mnt_flag & MNT_ROOTFS) ||
+       (mp->mnt_flag & MNT_UPDATE) ||
+       (mp->mnt_vnodecovered->v_op == &VMBlockVnodeOps)) {
+      return EOPNOTSUPP;
+   }
+
+   /*
+    * XXX Should only be unlocked if mnt_flag & MNT_UPDATE.
+    */
+   ASSERT_VOP_UNLOCKED(mp->mnt_vnodecovered, "Covered vnode already locked!");
+
+   /*
+    * Look up path to lower layer (VMBlock source / DnD staging area).
+    * (E.g., in the command "mount /tmp/VMwareDnD /var/run/vmblock",
+    * /tmp/VMwareDnD is the staging area.)
+    */
+   error = vfs_getopt(mp->mnt_optnew, "target", (void **)&target, &len);
+   if (error || target[len - 1] != '\0') {
+      return EINVAL;
+   }
+
+   pathname = uma_zalloc(VMBlockPathnameZone, M_WAITOK);
+   if (pathname == NULL) {
+      return ENOMEM;
+   }
+
+   if (strlcpy(pathname, target, MAXPATHLEN) >= MAXPATHLEN) {
+      uma_zfree(VMBlockPathnameZone, pathname);
+      return ENAMETOOLONG;
+   }
+
+   /*
+    * Find lower node and lock if not already locked.
+    */
+
+   NDINIT(ndp, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, target, compat_td);
+   error = namei(ndp);
+   if (error) {
+      NDFREE(ndp, 0);
+      uma_zfree(VMBlockPathnameZone, pathname);
+      return error;
+   }
+   NDFREE(ndp, NDF_ONLY_PNBUF);
+
+   /*
+    * Check multi VMBlock mount to avoid `lock against myself' panic.
+    */
+   lowerrootvp = ndp->ni_vp;
+   if (lowerrootvp == VPTOVMB(mp->mnt_vnodecovered)->lowerVnode) {
+      VMBLOCKDEBUG("VMBlockVFSMount: multi vmblock mount?\n");
+      vput(lowerrootvp);
+      uma_zfree(VMBlockPathnameZone, pathname);
+      return EDEADLK;
+   }
+
+   xmp = kmalloc(sizeof *xmp, M_VMBLOCKFSMNT, M_WAITOK);
+
+   /*
+    * Record pointer (mountVFS) to the staging area's file system.  Follow up
+    * by grabbing a VMBlockNode for our layer's root.
+    */
+   xmp->mountVFS = lowerrootvp->v_mount;
+   error = VMBlockNodeGet(mp, lowerrootvp, &vp, pathname);
+
+   /*
+    * Make sure the node alias worked
+    */
+   if (error) {
+      COMPAT_VOP_UNLOCK(vp, 0, compat_td);
+      vrele(lowerrootvp);
+      kfree(xmp, M_VMBLOCKFSMNT);   /* XXX */
+      uma_zfree(VMBlockPathnameZone, pathname);
+      return error;
+   }
+
+   /*
+    * Record a reference to the new filesystem's root vnode & mark it as such.
+    */
+   xmp->rootVnode = vp;
+   xmp->rootVnode->v_vflag |= VV_ROOT;
+
+   /*
+    * Unlock the node (either the lower or the alias)
+    */
+   COMPAT_VOP_UNLOCK(vp, 0, compat_td);
+
+   /*
+    * If the staging area is a local filesystem, reflect that here, too.  (We
+    * could potentially allow NFS staging areas.)
+    */
+   MNT_ILOCK(mp);
+   mp->mnt_flag |= lowerrootvp->v_mount->mnt_flag & MNT_LOCAL;
+#ifdef __DragonFly__
+   mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE;
+#endif
+   MNT_IUNLOCK(mp);
+
+   mp->mnt_data = (qaddr_t) xmp;
+
+   vfs_getnewfsid(mp);
+   vfs_mountedfrom(mp, target);
+
+   VMBLOCKDEBUG("VMBlockVFSMount: lower %s, alias at %s\n",
+      mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVFSUnmount --
+ *
+ *      "VFS_UNMOUNT(9) -- unmount a filesystem."
+ *
+ * Results:
+ *      Zero on success, else an appropriate system error.
+ *
+ * Side effects:
+ *      VMBlocks on all filesystems are removed.  (Expecting vmblockfs to
+ *      be mounted only once.)
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+#ifdef __DragonFly__
+VMBlockVFSUnmount(struct mount *mp,    // IN: filesystem to unmount
+                  int mntflags)        // IN: unmount(2) flags (ex: MNT_FORCE)
+#else
+VMBlockVFSUnmount(struct mount *mp,    // IN: filesystem to unmount
+                  int mntflags,        // IN: unmount(2) flags (ex: MNT_FORCE)
+                  struct thread *td)   // IN: caller's kernel thread context
+#endif
+{
+   struct VMBlockMount *xmp;
+   struct vnode *vp;
+   void *mntdata;
+   int error;
+   int flags = 0, removed = 0;
+
+   VMBLOCKDEBUG("VMBlockVFSUnmount: mp = %p\n", (void *)mp);
+
+   xmp = MNTTOVMBLOCKMNT(mp);
+   vp = xmp->rootVnode;
+
+   VI_LOCK(vp);
+
+   /*
+    * VMBlocks reference the root vnode.  This check returns EBUSY if
+    * VMBlocks still exist & the user isn't forcing us out.
+    */
+   if ((vp->v_usecount > 1) && !(mntflags & MNT_FORCE)) {
+      VI_UNLOCK(vp);
+      return EBUSY;
+   }
+
+   /*
+    * FreeBSD forbids acquiring sleepable locks (ex: sx locks) while holding
+    * non-sleepable locks (ex: mutexes).  The vnode interlock acquired above
+    * is a mutex, and the Block* routines involve sx locks, so we need to
+    * yield the interlock.
+    *
+    * In order to do this safely, we trade up to locking the entire vnode,
+    * and indicate to the lock routine that we hold the interlock.  The lock
+    * transfer will happen atomically.  (Er, at least within the scope of
+    * the vnode subsystem.)
+    */
+   COMPAT_VOP_LOCK(vp, LK_EXCLUSIVE|LK_RETRY|LK_INTERLOCK, compat_td);
+
+   removed = BlockRemoveAllBlocks(OS_UNKNOWN_BLOCKER);
+
+   VI_LOCK(vp);
+   vp->v_usecount -= removed;
+   VI_UNLOCK(vp);
+   COMPAT_VOP_UNLOCK(vp, 0, compat_td);
+
+   if (mntflags & MNT_FORCE) {
+      flags |= FORCECLOSE;
+   }
+
+   /* There is 1 extra root vnode reference (xmp->rootVnode). */
+   error = vflush(mp, 1, flags, compat_td);
+   if (error) {
+      return error;
+   }
+
+   /*
+    * Finally, throw away the VMBlockMount structure
+    */
+   mntdata = mp->mnt_data;
+   mp->mnt_data = 0;
+   kfree(mntdata, M_VMBLOCKFSMNT);
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVFSRoot --
+ *
+ *      "VFS_ROOT -- return the root vnode of a file system."
+ *
+ * Results:
+ *      Zero.
+ *
+ * Side effects:
+ *      Root vnode is locked.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+#ifdef __DragonFly__
+VMBlockVFSRoot(struct mount *mp,        // IN: vmblock file system
+               int flags,               // IN: lockmgr(9) flags
+               struct vnode **vpp)      // OUT: root vnode
+#else
+VMBlockVFSRoot(struct mount *mp,        // IN: vmblock file system
+               int flags,               // IN: lockmgr(9) flags
+               struct vnode **vpp,      // OUT: root vnode
+               struct thread *td)       // IN: caller's thread context
+#endif
+{
+   struct vnode *vp;
+
+   /*
+    * Return locked reference to root.
+    */
+   vp = MNTTOVMBLOCKMNT(mp)->rootVnode;
+   VREF(vp);
+   compat_vn_lock(vp, flags | LK_RETRY, compat_td);
+   *vpp = vp;
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVFSStatFS --
+ *
+ *      "VFS_STATFS -- return file system status."  We pass the request to the
+ *      lower layer, but return only the "interesting" bits.  (E.g., fs type,
+ *      sizes, usage, etc.)
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+#ifdef __DragonFly__
+VMBlockVFSStatFS(struct mount *mp,      // IN: vmblock file system
+                 struct statfs *sbp)    // OUT: statfs(2) arg container
+#else
+VMBlockVFSStatFS(struct mount *mp,      // IN: vmblock file system
+                 struct statfs *sbp,    // OUT: statfs(2) arg container
+                 struct thread *td)     // IN: caller's thread context
+#endif
+{
+   int error;
+   struct statfs mstat;
+
+   VMBLOCKDEBUG("VMBlockVFSStatFS(mp = %p, vp = %p->%p)\n", (void *)mp,
+       (void *)MNTTOVMBLOCKMNT(mp)->rootVnode,
+       (void *)VMBVPTOLOWERVP(MNTTOVMBLOCKMNT(mp)->rootVnode));
+
+   bzero(&mstat, sizeof mstat);
+
+   error = COMPAT_VFS_STATFS(MNTTOVMBLOCKMNT(mp)->mountVFS, &mstat, compat_td);
+   if (error) {
+      return error;
+   }
+
+   /* now copy across the "interesting" information and fake the rest */
+   sbp->f_type = mstat.f_type;
+   sbp->f_flags = mstat.f_flags;
+   sbp->f_bsize = mstat.f_bsize;
+   sbp->f_iosize = mstat.f_iosize;
+   sbp->f_blocks = mstat.f_blocks;
+   sbp->f_bfree = mstat.f_bfree;
+   sbp->f_bavail = mstat.f_bavail;
+   sbp->f_files = mstat.f_files;
+   sbp->f_ffree = mstat.f_ffree;
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVFSSync --
+ *
+ *      "VFS_SYNC -- flush unwritten data."  Since there's no caching at our
+ *      layer, this is a no-op.
+ *
+ * Results:
+ *      Zero.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+#ifdef __DragonFly__
+VMBlockVFSSync(struct mount *mp,        // Ignored
+               int waitfor)             // Ignored
+#else
+VMBlockVFSSync(struct mount *mp,        // Ignored
+               int waitfor,             // Ignored
+               struct thread *td)       // Ignored
+#endif
+{
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVFSVGet --
+ *
+ *      "VFS_VGET -- convert an inode number to a vnode."
+ *
+ * Results:
+ *      Zero on success, otherwise an appropriate system error.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVFSVGet(struct mount *mp,        // IN: vmblock file system
+               ino_t ino,               // IN: requested inode number
+               int flags,               // IN: vget(9) locking flags
+               struct vnode **vpp)      // OUT: located vnode
+{
+   int error;
+   error = VFS_VGET(MNTTOVMBLOCKMNT(mp)->mountVFS, ino, flags, vpp);
+   if (error) {
+      return error;
+   }
+
+   return VMBlockNodeGet(mp, *vpp, vpp, NULL);
+}
diff --git a/sys/dev/virtual/vmware/vmblock/vmblock.h b/sys/dev/virtual/vmware/vmblock/vmblock.h
new file mode 100644
index 0000000..009ec58
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/vmblock.h
@@ -0,0 +1,178 @@
+/*********************************************************
+ * Copyright (C) 2006-2008 VMware, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of VMware Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission of VMware Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *********************************************************/
+
+/*
+ * vmblock.h --
+ *
+ *   User-level interface to the vmblock device.
+ *
+ *   VMBLOCK_DEVICE should be opened with VMBLOCK_DEVICE_MODE mode. Then
+ *   VMBLOCK_CONTROL should be called to perform blocking operations.
+ *   The links which can be blocked are in the directory VMBLOCK_MOUNT_POINT.
+ *
+ *   VMBLOCK_CONTROL takes the file descriptor of the VMBLOCK_DEVICE, an
+ *   operation, and the path of the target of the file being operated on (if
+ *   applicable).
+ *
+ *   The operation should be one of:
+ *   VMBLOCK_ADD_FILEBLOCK
+ *   VMBLOCK_DEL_FILEBLOCK
+ *   VMBLOCK_LIST_FILEBLOCKS
+ *
+ *   path should be something in /tmp/VMwareDnD/ rather than in
+ *   VMBLOCK_MOUNT_POINT.
+ *
+ *   VMBLOCK_CONTROL returns 0 on success or returns -1 and sets errno on
+ *   failure.
+ */
+
+#ifndef _VMBLOCK_H_
+#define _VMBLOCK_H_
+
+#if defined(sun) || defined(__DragonFly__)
+# include <sys/ioccom.h>
+#endif
+
+#if defined(__DragonFly__)
+# include <sys/param.h>
+#endif
+
+
+/*
+ * FUSE definitions. They are supposed to be used by userspace code and
+ * therefore not guarded by ARCH defines since FUSE can potentially
+ * be used on different operating systems.
+ */
+
+#define VMBLOCK_FUSE_ADD_FILEBLOCK     'a'
+#define VMBLOCK_FUSE_DEL_FILEBLOCK     'd'
+#ifdef VMX86_DEVEL
+# define VMBLOCK_FUSE_LIST_FILEBLOCKS  'l'
+#endif /* VMX86_DEVEL */
+
+/*
+ * If you try 'read'-ing from file descriptor vmblock-fuse is supposed
+ * to respond with the following. It is used to check whether we deal
+ * with FUSE or in-kernel implementation.
+ */
+#define VMBLOCK_FUSE_READ_RESPONSE     "I am VMBLOCK-FUSE"
+
+#define VMBLOCK_FUSE_FS_NAME           "fuse.vmware-vmblock"
+#define VMBLOCK_FUSE_MOUNT_POINT       "/var/run/vmblock-fuse"
+#define VMBLOCK_FUSE_CTRL_MNTPNT       "blockdir"
+#define VMBLOCK_FUSE_FS_ROOT           VMBLOCK_FUSE_MOUNT_POINT "/" VMBLOCK_FUSE_CTRL_MNTPNT
+#define VMBLOCK_FUSE_DEVICE_NAME       "dev"
+#define VMBLOCK_FUSE_DEVICE            VMBLOCK_FUSE_MOUNT_POINT "/" VMBLOCK_FUSE_DEVICE_NAME
+#define VMBLOCK_FUSE_DEVICE_MODE       O_RDWR
+
+/* Commands for the control half of vmblock driver */
+#if defined(vmblock_fuse)
+/* These definitions are for vmblock-fuse module itself */
+# include <unistd.h>
+# include <limits.h>
+# include <string.h>
+# include <errno.h>
+# include "vm_basic_types.h"
+# define VMBLOCK_ADD_FILEBLOCK         VMBLOCK_FUSE_ADD_FILEBLOCK
+# define VMBLOCK_DEL_FILEBLOCK         VMBLOCK_FUSE_DEL_FILEBLOCK
+# ifdef VMX86_DEVEL
+#  define VMBLOCK_LIST_FILEBLOCKS      VMBLOCK_FUSE_LIST_FILEBLOCKS
+# endif /* VMX86_DEVEL */
+/*
+ * Some of the following names don't actually make much sense on their own.
+ * They're used for consistency with the other ports. See the file header for
+ * explanations of what they're used for.
+ */
+# define VMBLOCK_FS_NAME               VMBLOCK_FUSE_FS_NAME
+# define VMBLOCK_DEVICE_NAME           VMBLOCK_FUSE_DEVICE_NAME
+# define VMBLOCK_CONTROL_MOUNTPOINT    VMBLOCK_FUSE_CTRL_MNTPNT
+# define VMBLOCK_FS_ROOT               VMBLOCK_FUSE_FS_ROOT
+# define VMBLOCK_DEVICE                VMBLOCK_FUSE_DEVICE
+# define VMBLOCK_DEVICE_MODE           VMBLOCK_FUSE_DEVICE_MODE
+# define VMBLOCK_MOUNT_POINT           VMBLOCK_FUSE_MOUNT_POINT
+
+#elif defined(linux)
+# define VMBLOCK_ADD_FILEBLOCK         98
+# define VMBLOCK_DEL_FILEBLOCK         99
+# ifdef VMX86_DEVEL
+#  define VMBLOCK_LIST_FILEBLOCKS      100
+# endif
+# define VMBLOCK_FS_NAME               "vmblock"
+# define VMBLOCK_CONTROL_DIRNAME       VMBLOCK_FS_NAME
+# define VMBLOCK_CONTROL_DEVNAME       "dev"
+# define VMBLOCK_CONTROL_MOUNTPOINT    "mountPoint"
+# define VMBLOCK_CONTROL_PROC_DIRNAME  "fs/" VMBLOCK_CONTROL_DIRNAME
+
+# define VMBLOCK_MOUNT_POINT            "/proc/" VMBLOCK_CONTROL_PROC_DIRNAME   \
+                                       "/" VMBLOCK_CONTROL_MOUNTPOINT
+# define VMBLOCK_FS_ROOT                VMBLOCK_MOUNT_POINT
+# define VMBLOCK_DEVICE                 "/proc/" VMBLOCK_CONTROL_PROC_DIRNAME   \
+                                       "/" VMBLOCK_CONTROL_DEVNAME
+# define VMBLOCK_DEVICE_MODE            O_WRONLY
+
+#elif defined(sun) || defined(__DragonFly__)
+# define VMBLOCK_FS_NAME                "vmblock"
+# define VMBLOCK_MOUNT_POINT            "/var/run/" VMBLOCK_FS_NAME
+# define VMBLOCK_FS_ROOT                VMBLOCK_MOUNT_POINT
+# define VMBLOCK_DEVICE                 VMBLOCK_MOUNT_POINT
+# define VMBLOCK_DEVICE_MODE            O_RDONLY
+# if defined(sun)                       /* if (sun) { */
+   /*
+    * Construct ioctl(2) commands for blocks.  _IO() is a helper macro to
+    * construct unique command values more easily.  I chose 'v' because I
+    * didn't see it being used elsewhere, and the command numbers begin at one.
+    */
+#  define VMBLOCK_ADD_FILEBLOCK          _IO('v', 1)
+#  define VMBLOCK_DEL_FILEBLOCK          _IO('v', 2)
+#  ifdef VMX86_DEVEL
+#   define VMBLOCK_LIST_FILEBLOCKS       _IO('v', 3)
+#  endif
+
+# elif defined(__DragonFly__)              /* } else if (FreeBSD) { */
+   /*
+    * Similar to Solaris, construct ioctl(2) commands for block operations.
+    * Since the FreeBSD implementation does not change the user's passed-in
+    * data (pathname), we use the _IOW macro to define commands which write
+    * to the kernel.  (As opposed to _IOR or _IOWR.)  Groups 'v' and 'V'
+    * are taken by terminal drivers, so I opted for group 'Z'.
+    */
+#  define VMBLOCK_ADD_FILEBLOCK          _IOW('Z', 1, char[MAXPATHLEN] )
+#  define VMBLOCK_DEL_FILEBLOCK          _IOW('Z', 2, char[MAXPATHLEN] )
+#  ifdef VMX86_DEVEL
+#   define VMBLOCK_LIST_FILEBLOCKS       _IO('Z', 3)
+#   define VMBLOCK_PURGE_FILEBLOCKS      _IO('Z', 4)
+#  endif
+
+# endif                                 /* } */
+#else
+# error "Unknown platform for vmblock."
+#endif
+
+#endif /* _VMBLOCK_H_ */
diff --git a/sys/dev/virtual/vmware/vmblock/vmblock_k.h b/sys/dev/virtual/vmware/vmblock/vmblock_k.h
new file mode 100644
index 0000000..f6b0e64
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/vmblock_k.h
@@ -0,0 +1,151 @@
+/* **********************************************************
+ * Copyright (C) 2007 VMware, Inc.  All Rights Reserved.
+ * **********************************************************/
+
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software donated to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)null.h	8.3 (Berkeley) 8/20/94
+ *
+ * $FreeBSD: src/sys/fs/nullfs/null.h,v 1.23 2005/03/15 13:49:33 jeff Exp $
+ */
+
+/*
+ * vmblock_k.h --
+ *
+ *      Defnitions for entire vmblock module.
+ */
+
+#ifndef _VMBLOCK_K_H_
+#define _VMBLOCK_K_H_
+
+#ifdef _KERNEL
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+
+#include "vm_basic_types.h"
+#include "vm_assert.h"
+#include "block.h"
+
+
+/*
+ * Macros
+ */
+
+#ifdef VMBLOCKFS_DEBUG
+# define VMBLOCKFSDEBUG(format, args...)       printf(format ,## args)
+#else
+# define VMBLOCKFSDEBUG(format, args...)
+#endif /* VMBLOCKFS_DEBUG */
+
+#define MNTTOVMBLOCKMNT(mp)    ((struct VMBlockMount *)((mp)->mnt_data))
+#define VPTOVMB(vp)            ((struct VMBlockNode *)(vp)->v_data)
+#define VMBTOVP(xp)            ((xp)->backVnode)
+
+/*
+ * Debug logging
+ */
+#define VMBLOCK_DEBUG           LOG_DEBUG
+#define VMBLOCK_ERROR           LOG_WARNING
+#define VMBLOCK_ENTRY_LOGLEVEL  LOG_DEBUG
+#define Warning(fmt, args...)   log(VMBLOCK_ERROR, fmt, ##args)
+
+#ifdef VMX86_DEVEL
+#   define LOG(level, fmt, args...)     printf(fmt, ##args)
+#   define VMBLOCKDEBUG(fmt, args...)   log(VMBLOCK_DEBUG, fmt, ##args)
+#   define Debug(level, fmt, args...)   log(VMBLOCK_DEBUG, fmt, ##args)
+#else
+#   define LOG(level, fmt, args...)
+#   define VMBLOCKDEBUG(fmt, args...)
+#   define Debug(level, fmt, args...)
+#endif
+
+
+/*
+ * Describes a single mount instance
+ */
+
+typedef struct VMBlockMount {
+   struct mount	*mountVFS;      /* Reference to mount parameters */
+   struct vnode	*rootVnode;     /* Reference to root vnode */
+} VMBlockMount;
+
+
+/*
+ * A cache of vnode references
+ */
+
+typedef struct VMBlockNode {
+   LIST_ENTRY(VMBlockNode) hashEntry;   /* Hash chain element (contains ptr to
+                                           next node, etc.) */
+   struct vnode *lowerVnode;            /* VREFed once */
+   struct vnode *backVnode;             /* Back pointer */
+   char          *name;                 /* Looked up path to vnode */
+} VMBlockNode;
+
+
+/*
+ * Global variables
+ */
+
+extern struct vop_ops VMBlockVnodeOps;
+extern struct objcache *VMBlockPathnameZone;
+
+
+/*
+ * Global functions
+ */
+
+int VMBlockInit(struct vfsconf *vfsp);
+int VMBlockUninit(struct vfsconf *vfsp);
+int VMBlockNodeGet(struct mount *mp, struct vnode *target, struct vnode **vpp,
+                   char *pathname);
+void VMBlockHashRem(struct VMBlockNode *xp);
+void VMBlockSetupFileOps(void);
+int VMBlockVopBypass(struct vop_generic_args *ap);
+
+#ifdef DIAGNOSTIC
+struct vnode *VMBlockCheckVp(struct vnode *vp, char *fil, int lno);
+# define VMBVPTOLOWERVP(vp)     VMBlockCheckVp((vp), __FILE__, __LINE__)
+#else
+# define VMBVPTOLOWERVP(vp)     (VPTOVMB(vp)->lowerVnode)
+#endif
+
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_VMBLOCKFSNODE);
+#endif
+
+#endif /* _KERNEL */
+#endif /* _VMBLOCK_K_H_ */
diff --git a/sys/dev/virtual/vmware/vmblock/vnops.c b/sys/dev/virtual/vmware/vmblock/vnops.c
new file mode 100644
index 0000000..f7e87cb
--- /dev/null
+++ b/sys/dev/virtual/vmware/vmblock/vnops.c
@@ -0,0 +1,1542 @@
+/* **********************************************************
+ * Copyright 2007 VMware, Inc.  All rights reserved.
+ * **********************************************************/
+
+/*
+ * vnops.c --
+ *
+ *      Vnode operations for the vmblock filesystem on FreeBSD.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * John Heidemann of the UCLA Ficus project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)null_vnops.c	8.6 (Berkeley) 5/27/95
+ *
+ * Ancestors:
+ *	@(#)lofs_vnops.c	1.2 (Berkeley) 6/18/92
+ *	...and...
+ *	@(#)nullfs_vnops.c 1.20 92/07/07 UCLA Ficus project
+ *
+ * $FreeBSD: src/sys/fs/nullfs/null_vnops.c,v 1.87.2.3 2006/03/13 03:05:26 jeff Exp $
+ */
+
+/*
+ * NB:  The following is the introductory commentary from FreeBSD's
+ * null_vnops.c, which VMBlockFS is heavily based on.  It was kept intact in
+ * order to provide a better conceptual introduction to FreeBSD's approach
+ * to stackable file systems.
+ */
+
+/*
+ * Null Layer
+ *
+ * (See mount_nullfs(8) for more information.)
+ *
+ * The null layer duplicates a portion of the filesystem name space under
+ * a new name.  In this respect, it is similar to the loopback filesystem.
+ * It differs from the loopback fs in two respects:  it is implemented
+ * using a stackable layers techniques, and its "null-node"s stack above
+ * all lower-layer vnodes, not just over directory vnodes.
+ *
+ * The null layer has two purposes.  First, it serves as a demonstration
+ * of layering by proving a layer which does nothing.  (It actually
+ * does everything the loopback filesystem does, which is slightly more
+ * than nothing.)  Second, the null layer can serve as a prototype layer.
+ * Since it provides all necessary layer framework, new filesystem layers
+ * can be created very easily be starting with a null layer.
+ *
+ * The remainder of this man page examines the null layer as a basis
+ * for constructing new layers.
+ *
+ *
+ * INSTANTIATING NEW NULL LAYERS
+ *
+ * New null layers are created with mount_nullfs(8).  Mount_nullfs(8)
+ * takes two arguments, the pathname of the lower vfs (target-pn)
+ * and the pathname where the null layer will appear in the namespace
+ * (alias-pn).  After the null layer is put into place, the contents of
+ * target-pn subtree will be aliased under alias-pn.
+ *
+ *
+ * OPERATION OF A NULL LAYER
+ *
+ * The null layer is the minimum filesystem layer, simply bypassing
+ * all possible operations to the lower layer for processing there.
+ * The majority of its activity centers on the bypass routine, through
+ * which nearly all vnode operations pass.
+ *
+ * The bypass routine accepts arbitrary vnode operations for handling by
+ * the lower layer.  It begins by examing vnode operation arguments and
+ * replacing any null-nodes by their lower-layer equivlants.  It then
+ * invokes the operation on the lower layer.  Finally, it replaces the
+ * null-nodes in the arguments and, if a vnode is return by the operation,
+ * stacks a null-node on top of the returned vnode.
+ *
+ * Although bypass handles most operations, vop_getattr, vop_lock,
+ * vop_unlock, vop_inactive, vop_reclaim, and vop_print are
+ * not bypassed. Vop_getattr must change the fsid being returned.
+ * Vop_lock and vop_unlock must handle any locking for the current
+ * vnode as well as pass the lock request down.  Vop_inactive and
+ * vop_reclaim are not bypassed so that they can handle freeing null-layer
+ * specific data. Vop_print is not bypassed to avoid excessive debugging
+ * information.  Also, certain vnode operations change the locking state
+ * within the operation (create, mknod, remove, link, rename, mkdir,
+ * rmdir, and symlink). Ideally these operations should not change the
+ * lock state, but should be changed to let the caller of the function
+ * unlock them. Otherwise all intermediate vnode layers (such as union,
+ * umapfs, etc) must catch these functions to do the necessary locking
+ * at their layer.
+ *
+ *
+ * INSTANTIATING VNODE STACKS
+ *
+ * Mounting associates the null layer with a lower layer, effect
+ * stacking two VFSes.  Vnode stacks are instead created on demand as
+ * files are accessed.
+ *
+ * The initial mount creates a single vnode stack for the root of the
+ * new null layer.  All other vnode stacks are created as a result of
+ * vnode operations on this or other null vnode stacks.
+ *
+ * New vnode stacks come into existance as a result of an operation
+ * which returns a vnode.  The bypass routine stacks a null-node above
+ * the new vnode before returning it to the caller.
+ *
+ * For example, imagine mounting a null layer with "mount_nullfs
+ * /usr/include /dev/layer/null".  Changing directory to /dev/layer/null
+ * will assign the root null-node (which was created when the null layer
+ * was mounted).  Now consider opening "sys".  A vop_lookup would be
+ * done on the root null-node.  This operation would bypass through
+ * to the lower layer which would return a vnode representing the UFS
+ * "sys".  Null_bypass then builds a null-node aliasing the UFS "sys"
+ * and returns this to the caller.  Later operations on the null-node
+ * "sys" will repeat this process when constructing other vnode stacks.
+ *
+ *
+ * CREATING OTHER FILE SYSTEM LAYERS
+ *
+ * One of the easiest ways to construct new filesystem layers is to make a
+ * copy of the null layer, rename all files and variables, and then begin
+ * modifing the copy.  Sed can be used to easily rename all variables.
+ *
+ * The umap layer is an example of a layer descended from the null layer.
+ *
+ *
+ * INVOKING OPERATIONS ON LOWER LAYERS
+ *
+ * There are two techniques to invoke operations on a lower layer when the
+ * operation cannot be completely bypassed.  Each method is appropriate
+ * in different situations.  In both cases, it is the responsibility of
+ * the aliasing layer to make the operation arguments "correct" for the
+ * lower layer by mapping a vnode arguments to the lower layer.
+ *
+ * The first approach is to call the aliasing layer's bypass routine.
+ * This method is most suitable when you wish to invoke the operation
+ * currently being handled on the lower layer.  It has the advantage that
+ * the bypass routine already must do argument mapping.  An example of
+ * this is vop_getattr in the null layer.
+ *
+ * A second approach is to directly invoke vnode operations on the
+ * lower layer with the VOP_OPERATIONNAME interface.  The advantage
+ * of this method is that it is easy to invoke arbitrary operations on
+ * the lower layer.  The disadvantage is that vnode arguments must be
+ * manualy mapped.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/sysctl.h>
+#include <sys/vnode.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include "compat_freebsd.h"
+#include <sys/priv.h>
+
+#include "vmblock_k.h"
+#include "vmblock.h"
+#include "block.h"
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
+#include <vm/vnode_pager.h>
+
+
+/*
+ * Local functions
+ */
+
+#if 0 /* XXX swildner */
+static fo_ioctl_t               VMBlockFileIoctl;
+static fo_close_t               VMBlockFileClose;
+static vop_access_t             VMBlockVopAccess;
+static vop_getattr_t            VMBlockVopGetAttr;
+static vop_getwritemount_t      VMBlockVopGetWriteMount;
+static vop_inactive_t           VMBlockVopInactive;
+static vop_ioctl_t              VMBlockVopIoctl;
+static vop_islocked_t           VMBlockVopIsLocked;
+static compat_vop_lock_t        VMBlockVopLock;
+static vop_lookup_t             VMBlockVopLookup;
+static vop_open_t               VMBlockVopOpen;
+static vop_print_t              VMBlockVopPrint;
+static vop_reclaim_t            VMBlockVopReclaim;
+static vop_rename_t             VMBlockVopRename;
+static vop_setattr_t            VMBlockVopSetAttr;
+static vop_unlock_t             VMBlockVopUnlock;
+#else
+//static fo_ioctl_t               VMBlockFileIoctl;
+//static fo_close_t               VMBlockFileClose;
+static int VMBlockVopAccess(struct vop_access_args *);
+static int VMBlockVopGetAttr(struct vop_getattr_args *);
+//static vop_getwritemount_t      VMBlockVopGetWriteMount;
+static int VMBlockVopInactive(struct vop_inactive_args *);
+static int VMBlockVopIoctl(struct vop_ioctl_args *);
+//static vop_islocked_t           VMBlockVopIsLocked;
+//static compat_vop_lock_t        VMBlockVopLock;
+//static vop_lookup_t             VMBlockVopLookup;
+static int VMBlockVopOpen(struct vop_open_args *);
+static int VMBlockVopPrint(struct vop_print_args *);
+static int VMBlockVopReclaim(struct vop_reclaim_args *);
+static int VMBlockVopNRename(struct vop_nrename_args *);
+static int VMBlockVopSetAttr(struct vop_setattr_args *);
+//static vop_unlock_t             VMBlockVopUnlock;
+#endif
+
+/*
+ * Local data
+ */
+
+/*
+ * The following is an ioctl(2) argument wrapper for VMBlockVopIoctl.
+ * See the VMBlockFileOps blurb below for details.
+ */
+struct VMBlockIoctlArgs {
+   struct file  *fileDesc;      // file descriptor receiving ioctl request
+   void         *data;          // user's ioctl argument
+};
+
+typedef struct VMBlockIoctlArgs VMBlockIoctlArgs;
+
+/*
+ * VMBlockFS vnode operations vector --
+ *   Following are the file system's entry points via VFS nodes (vnodes).
+ *   See vnode(9) and sys/vnode.h for more information.  For details on
+ *   the locking protocol[1], have a look at kern/vnode_if.src.
+ *
+ * 1.  Describes for which operations a vnode should be locked before
+ *     the operation is called or after it returns.
+ */
+
+struct vop_ops VMBlockVnodeOps = {
+   .vop_bypass =                  VMBlockVopBypass,
+   .vop_access =                  VMBlockVopAccess,
+   .vop_bmap =                    VOP_EOPNOTSUPP,
+   .vop_getattr =                 VMBlockVopGetAttr,
+   .vop_getwritemount =           VMBlockVopGetWriteMount,
+   .vop_inactive =                VMBlockVopInactive,
+   .vop_ioctl =                   VMBlockVopIoctl,
+   .vop_islocked =                VMBlockVopIsLocked,
+   .COMPAT_VOP_LOCK_OP_ELEMENT =  VMBlockVopLock,
+   .vop_lookup =                  VMBlockVopLookup,
+   .vop_open =                    VMBlockVopOpen,
+   .vop_print =                   VMBlockVopPrint,
+   .vop_reclaim =                 VMBlockVopReclaim,
+   .vop_nrename =                 VMBlockVopNRename,
+   .vop_setattr =                 VMBlockVopSetAttr,
+   .vop_strategy =                VOP_EOPNOTSUPP,
+   .vop_unlock =                  VMBlockVopUnlock,
+};
+
+
+
+/*
+ * VMBlockFS file descriptor operations vector --
+ *   There are a few special cases where we need to control behavior beyond
+ *   the file system layer.  For this we define our own fdesc op vector,
+ *   install our own handlers for these special cases, and fall back to the
+ *   badfileops vnode ops for everything else.
+ *
+ *   VMBlock instances are keyed on/indexed by the file descriptor that received
+ *   the ioctl request[1].  Since the relationship between file descriptors and
+ *   vnodes is N:1, we need to intercept ioctl requests at the file descriptor
+ *   level, rather than at the vnode level, in order to have a record of which
+ *   descriptor received the request.  Similarly, we need to remove VMBlocks
+ *   issued on a file descriptor when said descriptor is closed.
+ *
+ *   NOTICE --
+ *     This applies -only- when a user opens the FS mount point directly.  All
+ *     other files'/directories' file descriptor operations vectors are left
+ *     untouched.
+ *
+ * 1.  Keying on thread ID/process ID doesn't work because file descriptors
+ *     may be shared between threads/processes.  Clients may find blocks
+ *     removed unintentionally when the original issuing thread or process
+ *     dies, even though the same descriptor is open.
+ */
+
+static struct fileops VMBlockFileOps;
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockSetupFileOps --
+ *
+ *      Sets up secial file operations vector used for root vnode _only_
+ *      (see the comment for VMBlockFileOps above).
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+VMBlockSetupFileOps(void)
+{
+   VMBlockFileOps = badfileops;
+   VMBlockFileOps.fo_stat = vnops.fo_stat;
+   VMBlockFileOps.fo_flags = vnops.fo_flags;
+   VMBlockFileOps.fo_ioctl = VMBlockFileIoctl;
+   VMBlockFileOps.fo_close = VMBlockFileClose;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockFileIoctl --
+ *
+ *      Wrapper for VMBlockVopIoctl.  This is done to provide VMBlockVopIoctl
+ *      with information about the file descriptor which received the user's
+ *      ioctl request.
+ *
+ * Results:
+ *      Zero on success, otherwise an appropriate system error.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+VMBlockFileIoctl(struct file *fp,       // IN: user's file descriptor
+                 u_long command,        // IN: encoded ioctl command
+                 void *data,            // IN: opaque data argument
+                 struct ucred *cred,    // IN: caller's credentials
+                 struct thread *td)     // IN: caller's thread context
+{
+   VMBlockIoctlArgs args;
+   args.fileDesc = fp;
+   args.data = data;
+   return vnops.fo_ioctl(fp, command, &args, cred, td);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockFileClose --
+ *
+ *      Called when a file descriptor is closed.  Destroy all blocks opened
+ *      on this descriptor, then pass off to vn_closefile to handle any other
+ *      cleanup.
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *      (See vn_closefile for more information.)
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockFileClose(struct file *fp,       // IN: user's file descriptor
+                 struct thread *td)     // IN: caller's thread context
+{
+   struct vnode *vp;
+   int removed = 0;
+
+   vp = MNTTOVMBLOCKMNT(fp->f_vnode->v_mount)->rootVnode;
+   removed = BlockRemoveAllBlocks(fp);
+
+   VI_LOCK(vp);
+   vp->v_usecount -= removed;
+   VI_UNLOCK(vp);
+
+   return vnops.fo_close(fp, td);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopBypass --
+ *
+ *      Default routine for bypassing the VMBlockFS file system layer.
+ *
+ * Results:
+ *      Zero on success, or an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      Parameters passed in via ap->a_desc may be modified by the lower
+ *      layer's routines.
+ *
+ * Original function comment:
+ *	This is the 10-Apr-92 bypass routine.
+ *	   This version has been optimized for speed, throwing away some
+ *	safety checks.  It should still always work, but it's not as
+ *	robust to programmer errors.
+ *
+ *	In general, we map all vnodes going down and unmap them on the way back.
+ *	As an exception to this, vnodes can be marked "unmapped" by setting
+ *	the Nth bit in operation's vdesc_flags.
+ *
+ *	Also, some BSD vnode operations have the side effect of vrele'ing
+ *	their arguments.  With stacking, the reference counts are held
+ *	by the upper node, not the lower one, so we must handle these
+ *	side-effects here.  This is not of concern in Sun-derived systems
+ *	since there are no such side-effects.
+ *
+ *	This makes the following assumptions:
+ *	- only one returned vpp
+ *	- no INOUT vpp's (Sun's vop_open has one of these)
+ *	- the vnode operation vector of the first vnode should be used
+ *	  to determine what implementation of the op should be invoked
+ *	- all mapped vnodes are of our vnode-type (NEEDSWORK:
+ *	  problems on rmdir'ing mount points and renaming?)
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+VMBlockVopBypass(struct vop_generic_args *ap)
+/*
+struct vop_generic_args {
+   struct vnodeop_desc *a_desc; // IN/OUT: Vnode operation description; incl.
+                                //         pointers to operand vnode(s), user
+                                //         credentials, calling thread context,
+                                //         etc.
+};
+*/
+{
+   struct vnode **this_vp_p;
+   int error;
+   struct vnode *old_vps[VDESC_MAX_VPS];
+   struct vnode **vps_p[VDESC_MAX_VPS];
+   struct vnode ***vppp;
+   struct vnodeop_desc *descp = ap->a_desc;
+   int reles, i;
+
+#ifdef DIAGNOSTIC
+   /*
+    * We require at least one vp.
+    */
+   if (descp->vdesc_vp_offsets == NULL ||
+       descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET) {
+      panic ("VMBlockVopBypass: no vp's in map");
+   }
+#endif
+
+   /*
+    * Map the vnodes going in.  Later, we'll invoke the operation based on
+    * the first mapped vnode's operation vector.
+    */
+   reles = descp->vdesc_flags;
+   for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
+      if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET) {
+         break;   /* bail out at end of list */
+      }
+
+      vps_p[i] = this_vp_p =
+         VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap);
+
+      /*
+       * We're not guaranteed that any but the first vnode are of our type.
+       * Check for and don't map any that aren't.  (We must always map first
+       * vp or vclean fails.)
+       */
+      if (i && (*this_vp_p == NULLVP ||
+          (*this_vp_p)->v_op != &VMBlockVnodeOps)) {
+         old_vps[i] = NULLVP;
+      } else {
+         old_vps[i] = *this_vp_p;
+         *(vps_p[i]) = VMBVPTOLOWERVP(*this_vp_p);
+         /*
+          * XXX - Several operations have the side effect of vrele'ing their
+          * vp's.  We must account for that.  (This should go away in the
+          * future.)
+          */
+         if (reles & VDESC_VP0_WILLRELE) {
+            VREF(*this_vp_p);
+         }
+      }
+   }
+
+   /*
+    * Call the operation on the lower layer with the modified argument
+    * structure.
+    */
+   if (vps_p[0] && *vps_p[0]) {
+      error = VCALL(ap);
+   } else {
+      kprintf("VMBlockVopBypass: no map for %s\n", descp->vdesc_name);
+      error = EINVAL;
+   }
+
+   /*
+    * Maintain the illusion of call-by-value by restoring vnodes in the
+    * argument structure to their original value.
+    */
+   reles = descp->vdesc_flags;
+   for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
+      if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET) {
+         break;   /* bail out at end of list */
+      }
+      if (old_vps[i]) {
+         *(vps_p[i]) = old_vps[i];
+         if (reles & VDESC_VP0_WILLRELE) {
+            vrele(*(vps_p[i]));
+         }
+      }
+   }
+
+   /*
+    * Map the possible out-going vpp (Assumes that the lower layer always
+    * returns a VREF'ed vpp unless it gets an error.)
+    */
+   if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
+       !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
+       !error) {
+      /*
+       * XXX - even though some ops have vpp returned vp's, several ops
+       * actually vrele this before returning.  We must avoid these ops.
+       * (This should go away when these ops are regularized.)
+       */
+      if (descp->vdesc_flags & VDESC_VPP_WILLRELE) {
+         goto out;
+      }
+      vppp = VOPARG_OFFSETTO(struct vnode***, descp->vdesc_vpp_offset,ap);
+      if (*vppp) {
+         /* FIXME: set proper name for the vnode */
+         error = VMBlockNodeGet(old_vps[0]->v_mount, **vppp, *vppp, NULL);
+      }
+   }
+
+out:
+   return error;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopLookup --
+ *
+ *      "VOP_LOOKUP(9) -- lookup a component of a pathname"
+ *
+ * Results:
+ *      Zero if the component name is found.  EJUSTRETURN if the namei
+ *      operation is CREATE or RENAME, we're looking up the final component
+ *      name, and said operation would succeed.  Otherwise returns an
+ *      appropriate system error.
+ *
+ * Side effects:
+ *      Requested vnode is locked and returned in *ap->a_vpp.
+ *
+ * Original function comment:
+ *	We have to carry on the locking protocol on the null layer vnodes
+ *	as we progress through the tree. We also have to enforce read-only
+ *	if this layer is mounted read-only.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopLookup(struct vop_lookup_args *ap)
+/*
+struct vop_lookup_args {
+   struct vnode *dvp;           // IN: pointer to searched directory
+   struct vnode **vpp;          // OUT: if found, points to requested
+                                //      vnode; else NULL
+   struct componentname *cnp;   // IN: directory search context
+};
+*/
+{
+   struct componentname *cnp = ap->a_cnp;
+   COMPAT_THREAD_VAR(td, cnp->cn_thread);
+   struct vnode *dvp = ap->a_dvp;
+   struct vnode *vp, *ldvp, *lvp;
+   BlockHandle blockCookie;
+   int flags = cnp->cn_flags;
+   int error = 0;
+   char *pathname;
+   size_t pathname_len;
+
+   /*
+    * Fail attempts to modify a read-only filesystem w/o bothering with a
+    * lower-layer lookup.
+    */
+   if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+       (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
+      return EROFS;
+   }
+
+   /*
+    * Before looking in the lower layer, determine whether the search path
+    * should be blocked.  If so, do the following:
+    *   1.  Make a copy of the block pathname.  (BlockWaitOnFile may make
+    *       use of this, and our VMBlockNode may be destroyed while asleep
+    *       if user forcibly unmounts file system.)
+    *   2.  Bump up hold counts of current VMBlock directory vnode and its
+    *       lower layer counterpart.  This makes sure that at least they
+    *       aren't purged from memory while we sleep.
+    *   3.  Unlock & relock directory vnodes around sleeping.  This prevents
+    *       a cascading file system lookup deadlock.  (E.g., we have dvp locked,
+    *       but another thread trying to look up dvp will block, holding /its/
+    *       dvp's (dvp2) lock, and yet another thread would block looking up
+    *       dvp2 while holding its dvp (dvp3), etc.
+    *
+    * If we find we were forcibly unmounted, fail with EIO.
+    */
+
+   pathname = uma_zalloc(VMBlockPathnameZone, M_WAITOK);
+   if (pathname == NULL) {
+      return ENOMEM;
+   }
+
+   /*
+    * FIXME: we need to ensure that vnode always has name set up.
+    * Currently VMBlockVopBypass() may produce vnodes without a name.
+    */
+   pathname_len = strlcpy(pathname,
+                          VPTOVMB(dvp)->name ? VPTOVMB(dvp)->name : ".",
+                          MAXPATHLEN);
+   /*
+    * Make sure we have room in the buffer to add our component.
+    * + 1 is for separator (slash).
+    */
+   if (pathname_len + 1 + cnp->cn_namelen >= MAXPATHLEN) {
+      error = ENAMETOOLONG;
+      goto out;
+   }
+
+   if ((blockCookie = BlockLookup(pathname, OS_UNKNOWN_BLOCKER)) != NULL) {
+      int lkflags = compat_lockstatus(dvp->v_vnlock, td) & LK_TYPE_MASK;
+      lvp = VPTOVMB(dvp)->lowerVnode;
+      vhold(dvp);
+      vhold(lvp);
+      COMPAT_VOP_UNLOCK(dvp, 0, td);
+
+      error = BlockWaitOnFile(pathname, blockCookie);
+
+      COMPAT_VOP_LOCK(dvp, lkflags, td);
+      vdrop(lvp);
+      vdrop(dvp);
+      if (dvp->v_op != &VMBlockVnodeOps) {
+         Debug("%s: vmblockfs forcibly unmounted?\n", __func__);
+         error = EIO;
+      }
+
+      if (error) {
+         goto out;
+      }
+   }
+
+   /* We already verified that buffer is big enough. */
+   pathname[pathname_len] = '/';
+   bcopy(cnp->cn_nameptr, &pathname[pathname_len + 1], cnp->cn_namelen);
+   pathname[pathname_len + 1 + cnp->cn_namelen] = 0;
+
+   /*
+    * Although it is possible to call VMBlockVopBypass(), we'll do a direct
+    * call to reduce overhead
+    */
+   ldvp = VMBVPTOLOWERVP(dvp);
+   vp = lvp = NULL;
+
+   error = VOP_LOOKUP(ldvp, &lvp, cnp);
+   if (error == EJUSTRETURN && (flags & ISLASTCN) &&
+       (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+       (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) {
+      error = EROFS;
+   }
+
+   if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
+      /*
+       * Per VOP_LOOKUP(9), if looking up the current directory ("."), we bump
+       * our vnode's refcount.
+       */
+      if (ldvp == lvp) {
+         *ap->a_vpp = dvp;
+         VREF(dvp);
+         vrele(lvp);
+      } else {
+         error = VMBlockNodeGet(dvp->v_mount, lvp, &vp, pathname);
+         if (error) {
+            /* XXX Cleanup needed... */
+            panic("VMBlockNodeGet failed");
+         }
+         *ap->a_vpp = vp;
+         /* The vnode now owns pathname so don't try to free it below. */
+         pathname = NULL;
+      }
+   }
+
+out:
+   if (pathname) {
+      uma_zfree(VMBlockPathnameZone, pathname);
+   }
+   return error;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VMBlockVopOpen --
+ *
+ *      "The VOP_OPEN() entry point is called before a file is accessed by a
+ *      process..." - VOP_OPEN(9).  If the vnode in question is the file
+ *      system's root vnode, allow access only to the superuser.
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopOpen(struct vop_open_args *ap)
+/*
+struct vop_open_args {
+   struct vnode *vp;    // IN: vnode which ioctl issued upon
+   int fflag;           // IN: fdesc flags (see fcntl(2))
+   struct ucred *cred;  // IN: caller's credentials (usually real uid vs euid)
+   struct thread *td;   // IN: calling thread's context
+   FreeBSD <= 6 --
+      int fdidx;        // IN: file descriptor number alloc'd to this open()
+   FreeBSD >= 7 --
+      struct file *fp   // IN: struct associated with this particular open()
+};
+*/
+{
+   VMBlockMount *mp;
+   VMBlockNode *mip;
+   struct vnode *vp, *ldvp;
+   struct file *fp;
+   int retval;
+
+   vp = ap->a_vp;
+   ldvp = VMBVPTOLOWERVP(vp);
+   mip = VPTOVMB(ap->a_vp);
+
+   mp = MNTTOVMBLOCKMNT(ap->a_vp->v_mount);
+   if (ap->a_vp == mp->rootVnode) {
+      /*
+       * Opening the mount point is a special case.  First, only allow this
+       * access to the superuser.  Next, we install a custom fileops vector in
+       * order to trap the ioctl() and close() operations.  (See the *FileOps'
+       * descriptions for more details.)
+       *
+       * NB:  Allowing only the superuser to open this directory breaks
+       *      readdir() of the filesystem root for non-privileged users.
+       *
+       * Also, on FreeBSD 8.0 and newer we check for a specific module priv
+       * because none of the existing privs seemed to match very well.
+       */
+      if ((retval = compat_priv_check(ap->a_td, PRIV_DRIVER)) == 0) {
+#ifdef __DragonFly__
+         fp = ap->a_fp;
+#else
+         fp = ap->a_td->td_proc->p_fd->fd_ofiles[ap->a_fdidx];
+#endif
+         fp->f_ops = &VMBlockFileOps;
+      }
+   } else {
+      /*
+       * Pass off to the lower layer.  If lower layer mapped a VM object, copy
+       * its reference.
+       */
+      retval = VMBlockVopBypass(&ap->a_gen);
+      if (retval == 0) {
+         vp->v_object = ldvp->v_object;
+      }
+   }
+
+   return retval;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopSetAttr --
+ *
+ *      "VOP_SETATTR(9) -- set attributes on a file or directory."
+ *
+ *      This version is simpler than the original null_setattr as it only
+ *      tests whether the user is attempting an operation in a read-only
+ *      file system.  Beyond that, it defers judgment about the validity of
+ *      the request to the lower layer via vop_bypass.
+ *
+ * Results:
+ *      Zero on success, else an appropriate system error.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Original function comment:
+ *      Setattr call. Disallow write attempts if the layer is mounted read-
+ *      only.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopSetAttr(struct vop_setattr_args *ap)
+/*
+struct vop_setattr_args {
+   struct vnode *vp;    // IN: vnode operand
+   struct vattr *vap;   // IN: attributes
+   struct ucred *cred;  // IN: caller's credentials
+   struct thread *td;   // IN: caller's thread context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+
+   if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+      return EROFS;
+   }
+
+   return VMBlockVopBypass((struct vop_generic_args *)ap);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VMBlockVopIoctl --
+ *
+ *      Handle ioctl(2) requests to add and remove file blocks.  Ioctl
+ *      commands are defined in public/vmblock.h.
+ *
+ * Results:
+ *      Zero on success, otherwise an appropriate error is returned.
+ *
+ * Side effects
+ *      A block may be placed on or removed from a file.  The root vnode's
+ *      reference count will be incremented when a block is successfully added,
+ *      and it will be decremented when a block is removed.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopIoctl(struct vop_ioctl_args *ap)      // IN/OUT: ioctl parameters
+/*
+struct vop_ioctl_args {
+   struct vnode *vp;    // IN: vnode which ioctl issued upon
+   u_long command;      // IN: ioctl command
+   caddr_t data;        // IN: ioctl parameter (e.g., pathname)
+   int fflag;           // IN: fcntl style flags (no-op?)
+   struct ucred *cred;  // IN: caller's credentials (usually real uid vs euid)
+   struct thread *td;   // IN: calling thread's context
+};
+*/
+{
+   VMBlockIoctlArgs *ioctlArgs = (VMBlockIoctlArgs *)ap->a_data;
+   VMBlockMount *mp;
+   COMPAT_THREAD_VAR(td, ap->a_td);
+   struct vnode *vp = ap->a_vp;
+   char *pathbuf = NULL;
+   int ret = 0, pathlen;
+
+   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockVopIoctl: entry\n");
+
+   /*
+    * The operand vnode is passed in unlocked, so test a few things before
+    * proceeding.
+    *   1.  Make sure we're still dealing with a VMBlock vnode.  Note
+    *       that this test -must- come before the next one.  Otherwise v_mount
+    *       may be invalid.
+    *   2.  Make sure the filesystem isn't being unmounted.
+    */
+   COMPAT_VOP_LOCK(vp, LK_EXCLUSIVE|LK_RETRY, td);
+   if (vp->v_op != &VMBlockVnodeOps ||
+       vp->v_mount->mnt_kern_flag & MNTK_UNMOUNT) {
+      COMPAT_VOP_UNLOCK(vp, 0, td);
+      return EBADF;
+   }
+
+   /*
+    * At this layer/in this file system, only the root vnode handles ioctls,
+    * and only the superuser may open the root vnode.  If we're not given
+    * the root vnode, simply bypass to the next lower layer.
+    */
+   mp = MNTTOVMBLOCKMNT(vp->v_mount);
+   if (vp != mp->rootVnode) {
+      /*
+       * VMBlockFileIoctl wraps the user's data in a special structure which
+       * includes the user's file descriptor, so we must unwrap the data
+       * argument before passing to the lower layer.
+       */
+      ap->a_data = ioctlArgs->data;
+      COMPAT_VOP_UNLOCK(vp, 0, td);
+      return VMBlockVopBypass((struct vop_generic_args *)ap);
+   }
+
+   pathbuf = uma_zalloc(VMBlockPathnameZone, M_WAITOK);
+
+   switch (ap->a_command) {
+   case VMBLOCK_ADD_FILEBLOCK:
+   case VMBLOCK_DEL_FILEBLOCK:
+   {
+      /*
+       * Trim trailing slashes
+       */
+      pathlen = strlcpy(pathbuf, ioctlArgs->data, MAXPATHLEN);
+      pathlen = MIN(pathlen, MAXPATHLEN);
+      while (pathlen > 0 && pathbuf[pathlen - 1] == '/') {
+         pathbuf[pathlen - 1] = '\0';
+         pathlen--;
+      }
+
+      VMBLOCKDEBUG("%s: %s on %s\n", __func__,
+                   (ap->a_command == VMBLOCK_ADD_FILEBLOCK) ? "add" : "del",
+                   pathbuf);
+
+      /*
+       * Don't block the mount point!
+       */
+      if (!strcmp(VPTOVMB(vp)->name, pathbuf)) {
+         ret = EINVAL;
+      } else {
+         ret = (ap->a_command == VMBLOCK_ADD_FILEBLOCK) ?
+                  BlockAddFileBlock(pathbuf, ioctlArgs->fileDesc) :
+                  BlockRemoveFileBlock(pathbuf, ioctlArgs->fileDesc);
+
+         /*
+          * When adding a block, bump the reference count on the root vnode.  If
+          * removing a block, decrement the reference count.  Of course, only do
+          * so if the action succeeds!
+          */
+         if (ret == 0) {
+            VI_LOCK(vp);
+            vp->v_usecount += (ap->a_command == VMBLOCK_ADD_FILEBLOCK) ? 1 : -1;
+            VI_UNLOCK(vp);
+         }
+      }
+      break;
+   }
+#ifdef VMX86_DEVEL
+   case VMBLOCK_LIST_FILEBLOCKS:
+      BlockListFileBlocks();
+      ret = 0;
+      break;
+   case VMBLOCK_PURGE_FILEBLOCKS:
+      {
+         int removed = 0;
+         removed = BlockRemoveAllBlocks(OS_UNKNOWN_BLOCKER);
+         VI_LOCK(vp);
+         vp->v_usecount -= removed;
+         VI_UNLOCK(vp);
+      }
+      ret = 0;
+      break;
+#endif
+   default:
+      Warning("VMBlockVopIoctl: unknown command (%lu) received.\n", ap->a_command);
+      ret = EOPNOTSUPP;
+   }
+
+   COMPAT_VOP_UNLOCK(vp, 0, td);
+   if (pathbuf) {
+      uma_zfree(VMBlockPathnameZone, pathbuf);
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VMBlockVopGetAttr --
+ *
+ *      Query the underlying filesystem for file/directory information.
+ *      Also fixup fsid to be ours rather than that of the underlying fs.
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopGetAttr(struct vop_getattr_args *ap)
+/*
+struct vop_getattr_args {
+   struct vnode *vp;    // IN: operand vnode
+   struct vattr *vap;   // OUT: vnode's parameters
+   struct ucred *ucred; // IN: caller's credentials
+   struct thread *td;   // IN: caller's thread context
+};
+*/
+{
+   int error;
+
+   if ((error = VMBlockVopBypass((struct vop_generic_args *)ap)) != 0) {
+      return error;
+   }
+
+   ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
+   return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VMBlockVopAccess --
+ *
+ *      "VOP_ACCESS(9) -- check access permissions of a file or Unix domain
+ *      socket."  We handle this to disallow write access if our layer is,
+ *      for whatever reason, mounted read-only.
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopAccess(struct vop_access_args *ap)
+/*
+struct vop_access_args {
+   struct vnode *vp;    // IN: operand vnode
+   int mode;            // IN: access(2) flags
+   struct vattr *vap;   // OUT: vnode's parameters
+   struct ucred *ucred; // IN: caller's credentials
+   struct thread *td;   // IN: caller's thread context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   compat_accmode_t mode = ap->compat_a_accmode;
+
+   /*
+    * Disallow write attempts on read-only layers; unless the file is a
+    * socket, fifo, or a block or character device resident on the filesystem.
+    */
+   if (mode & VWRITE) {
+      switch (vp->v_type) {
+      case VDIR:
+      case VLNK:
+      case VREG:
+         if (vp->v_mount->mnt_flag & MNT_RDONLY) {
+            return EROFS;
+         }
+         break;
+      default:
+         break;
+      }
+   }
+   return VMBlockVopBypass((struct vop_generic_args *)ap);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * VMBlockRename --
+ *
+ *      "VOP_RENAME(9) -- rename a file."
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Original function comment:
+ *      We handle this to eliminate null FS to lower FS file moving. Don't
+ *      know why we don't allow this, possibly we should.
+ *----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopRename(struct vop_rename_args *ap)
+/*
+struct vop_rename_args {
+   struct vnode *fdvp;          // IN: source directory
+   struct vnode *fvp;           // IN: source file
+   struct componentname *fcnp;  // IN: source's path lookup state
+   struct vnode *tdvp;          // IN: destination directory
+   struct vnode *tvp;           // IN: destination file
+   struct componentname *tcnp;  // IN: destination's path lookup state
+};
+*/
+{
+   struct vnode *tdvp = ap->a_tdvp;
+   struct vnode *fvp = ap->a_fvp;
+   struct vnode *fdvp = ap->a_fdvp;
+   struct vnode *tvp = ap->a_tvp;
+
+   /* Check for cross-device rename. */
+   if ((fvp->v_mount != tdvp->v_mount) ||
+       (tvp && (fvp->v_mount != tvp->v_mount))) {
+      if (tdvp == tvp) {
+         vrele(tdvp);
+      } else {
+         vput(tdvp);
+      }
+      if (tvp) {
+         vput(tvp);
+      }
+      vrele(fdvp);
+      vrele(fvp);
+      return EXDEV;
+   }
+
+   return VMBlockVopBypass((struct vop_generic_args *)ap);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopLock --
+ *
+ *      Acquire a vnode lock.
+ *
+ * Results:
+ *      Zero on success, otherwise an error is returned.
+ *
+ * Side effects:
+ *      Upper & lower layers share a lock, so both vnodes will be considered
+ *      locked.
+ *
+ * Original function comment:
+ *      We need to process our own vnode lock and then clear the interlock flag
+ *      as it applies only to our vnode, not the vnodes below us on the stack.
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopLock(compat_vop_lock_args *ap)
+/*
+struct vop_lock_args {
+   struct vnode *vp;    // IN: vnode operand
+   int flags;           // IN: lockmgr(9) flags
+   struct thread *td;   // IN: calling thread's context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   int flags = ap->a_flags;
+   COMPAT_THREAD_VAR(td, ap->a_td);
+   struct VMBlockNode *nn;
+   struct vnode *lvp;
+   int error;
+
+
+   if ((flags & LK_INTERLOCK) == 0) {
+      VI_LOCK(vp);
+      ap->a_flags = flags |= LK_INTERLOCK;
+   }
+   nn = VPTOVMB(vp);
+   /*
+    * If we're still active we must ask the lower layer to lock as ffs
+    * has special lock considerations in it's vop lock. -- FreeBSD
+    */
+   if (nn != NULL && (lvp = VMBVPTOLOWERVP(vp)) != NULL) {
+      VI_LOCK_FLAGS(lvp, MTX_DUPOK);
+      VI_UNLOCK(vp);
+      /*
+       * We have to hold the vnode here to solve a potential reclaim race.
+       * If we're forcibly vgone'd while we still have refs, a thread
+       * could be sleeping inside the lowervp's vop_lock routine.  When we
+       * vgone we will drop our last ref to the lowervp, which would
+       * allow it to be reclaimed.  The lowervp could then be recycled,
+       * in which case it is not legal to be sleeping in it's VOP.
+       * We prevent it from being recycled by holding the vnode here.
+       */
+      vholdl(lvp);
+      error = COMPAT_VOP_LOCK(lvp, flags, td);
+
+      /*
+       * We might have slept to get the lock and someone might have clean
+       * our vnode already, switching vnode lock from one in lowervp
+       * to v_lock in our own vnode structure.  Handle this case by
+       * reacquiring correct lock in requested mode.
+       */
+      if (VPTOVMB(vp) == NULL && error == 0) {
+         ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
+         switch (flags & LK_TYPE_MASK) {
+         case LK_SHARED:
+            ap->a_flags |= LK_SHARED;
+            break;
+         case LK_UPGRADE:
+         case LK_EXCLUSIVE:
+            ap->a_flags |= LK_EXCLUSIVE;
+            break;
+         default:
+            panic("Unsupported lock request %d\n",
+                ap->a_flags);
+         }
+         COMPAT_VOP_UNLOCK(lvp, 0, td);
+         error = vop_stdlock(ap);
+      }
+      vdrop(lvp);
+   } else {
+      error = vop_stdlock(ap);
+   }
+
+   return error;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopUnlock --
+ *
+ *      Release a vnode lock.
+ *
+ * Results:
+ *      Zero on success, an appropriate system error otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ * Original function comment:
+ *      We need to process our own vnode unlock and then clear the interlock
+ *      flag as it applies only to our vnode, not the vnodes below us on
+ *      the stack.
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopUnlock(struct vop_unlock_args *ap)
+/*
+struct vop_unlock_args {
+   struct vnode *vp;    // IN: vnode operand
+   int flags;           // IN: lock request flags (see lockmgr(9))
+   struct thread *td;   // IN: calling thread's context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   int flags = ap->a_flags;
+   COMPAT_THREAD_VAR(td, ap->a_td);
+   struct VMBlockNode *nn;
+   struct vnode *lvp;
+   int error;
+
+   /*
+    * If caller already holds interlock, drop it.  (Per VOP_UNLOCK() API.)
+    * Also strip LK_INTERLOCK from flags passed to lower layer.
+    */
+   if ((flags & LK_INTERLOCK) != 0) {
+      VI_UNLOCK(vp);
+      ap->a_flags = flags &= ~LK_INTERLOCK;
+   }
+   nn = VPTOVMB(vp);
+   if (nn != NULL && (lvp = VMBVPTOLOWERVP(vp)) != NULL) {
+      error = COMPAT_VOP_UNLOCK(lvp, flags, td);
+   } else {
+      error = vop_stdunlock(ap);
+   }
+
+   return error;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopIsLocked --
+ *
+ *      Test whether a vnode is locked.
+ *
+ * Results:
+ *      Zero if locked, non-zero otherwise.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopIsLocked(struct vop_islocked_args *ap)
+/*
+struct vop_islocked_args {
+   struct vnode *vp;    // IN: vnode operand
+   struct thread *td;   // IN: calling thread's context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   COMPAT_THREAD_VAR(td, ap->a_td);
+
+   return compat_lockstatus(vp->v_vnlock, td);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopInactive --
+ *
+ *      "VOP_INACTIVE() is called when the kernel is no longer using the vnode.
+ *      This may be because the reference count reaches zero or it may be that
+ *      the file system is being forcibly unmounted while there are open files.
+ *      It can be used to reclaim space for `open but deleted' files."
+ *
+ * Results:
+ *      Zero.
+ *
+ * Side effects:
+ *      If this vnode's reference is zero, vrecycle() will handle induce
+ *      cleanup.
+ *
+ * Original function comment:
+ *	There is no way to tell that someone issued remove/rmdir operation
+ *	on the underlying filesystem. For now we just have to release lowevrp
+ *	as soon as possible.
+ *
+ *	Note, we can't release any resources nor remove vnode from hash before
+ *	appropriate VXLOCK stuff is is done because other process can find
+ *	this vnode in hash during inactivation and may be sitting in vget()
+ *	and waiting for VMBlockVopInactive to unlock vnode. Thus we will do
+ *	all those in VOP_RECLAIM.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopInactive(struct vop_inactive_args *ap)
+/*
+struct vop_inactive_args {
+   struct vnode *vp;    // IN: vnode operand
+   struct thread *td;   // IN: calling thread's context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   struct thread *td = ap->a_td;
+
+   vp->v_object = NULL;
+
+   /*
+    * If this is the last reference, then free up the vnode so as not to
+    * tie up the lower vnode.
+    */
+   vrecycle(vp, td);
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopReclaim --
+ *
+ *      "VOP_RECLAIM() is called when a vnode is being reused for a
+ *      different file system.  Any file system specific resources
+ *      associated with the vnode should be freed."
+ *
+ * Results:
+ *      Returns zero.
+ *
+ * Side effects:
+ *      If node is an associate VMBlockNode, it's removed from
+ *      the VMBlockNode hash and freed.  Reference to the lower vnode, if
+ *      it exists, is also dropped.
+ *
+ * Original function comment:
+ *      Now, the VXLOCK is in force and we're free to destroy the null vnode.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopReclaim(struct vop_reclaim_args *ap)
+/*
+struct vop_reclaim_args {
+   struct vnode *vp;    // IN: vnode operand
+   struct thread *td;   // IN: calling thread's context
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   struct VMBlockNode *xp = VPTOVMB(vp);
+   struct vnode *lowervp = xp->lowerVnode;
+   struct lock *vnlock;
+
+   KASSERT(lowervp != NULL, ("reclaiming node with no lower vnode"));
+
+   VMBlockHashRem(xp);
+
+   /*
+    * Use the interlock to protect the clearing of v_data to
+    * prevent faults in VMBlockVopLock().
+    */
+   VI_LOCK(vp);
+   vp->v_data = NULL;
+   vp->v_object = NULL;
+   vnlock = vp->v_vnlock;
+
+   /*
+    * Reassign lock pointer to this vnode's lock.  (Originally assigned
+    * to the lower layer's lock.)
+    */
+   vp->v_vnlock = &vp->v_lock;
+   compat_lockmgr(vp->v_vnlock, LK_EXCLUSIVE|LK_INTERLOCK, VI_MTX(vp), curthread);
+   vput(lowervp);
+
+   /*
+    * Clean up VMBlockNode attachment.
+    */
+   if (xp->name) {
+      uma_zfree(VMBlockPathnameZone, xp->name);
+   }
+   kfree(xp, M_VMBLOCKFSNODE);
+
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopPrint --
+ *
+ *      "VOP_PRINT -- print debugging information"
+ *
+ * Results:
+ *      Zero.  Always.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopPrint(struct vop_print_args *ap)
+/*
+struct vop_print_args {
+   struct vnode *vp;    // IN: vnode operand
+};
+*/
+{
+   struct vnode *vp = ap->a_vp;
+   kprintf("\tvp=%p, lowervp=%p\n", vp, VMBVPTOLOWERVP(vp));
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VMBlockVopGetWriteMount --
+ *
+ *      When the caller wishes to begin a write operation, we need to bump
+ *      the count of write operations on the destination file system.  This
+ *      routine passes the request down.  "Real" file systems will usually
+ *      call vop_stdgetwritemount().
+ *
+ * Results:
+ *      Zero.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+VMBlockVopGetWriteMount(struct vop_getwritemount_args *ap)
+/*
+struct vop_getwritemount_args {
+   struct vnode *vp;    // IN: vnode operand
+   struct mount **mpp;  // OUT: pointer to filesystem where write operation
+                        //      will actually occur
+};
+*/
+{
+   struct VMBlockNode *xp;
+   struct vnode *lowervp;
+   struct vnode *vp;
+
+   vp = ap->a_vp;
+   VI_LOCK(vp);
+   xp = VPTOVMB(vp);
+   if (xp && (lowervp = xp->lowerVnode)) {
+      VI_LOCK_FLAGS(lowervp, MTX_DUPOK);
+      VI_UNLOCK(vp);
+      vholdl(lowervp);
+      VI_UNLOCK(lowervp);
+      VOP_GETWRITEMOUNT(lowervp, ap->a_mpp);
+      vdrop(lowervp);
+   } else {
+      VI_UNLOCK(vp);
+      *(ap->a_mpp) = NULL;
+   }
+   return 0;
+}
diff --git a/sys/gnu/Makefile b/sys/gnu/Makefile
index 9cd3fec..4ac270d 100644
--- a/sys/gnu/Makefile
+++ b/sys/gnu/Makefile
@@ -1,3 +1,3 @@
-SUBDIR=	vfs
+SUBDIR=	dev vfs
 
 .include <bsd.subdir.mk>
diff --git a/sys/gnu/dev/Makefile b/sys/gnu/dev/Makefile
new file mode 100644
index 0000000..befa834
--- /dev/null
+++ b/sys/gnu/dev/Makefile
@@ -0,0 +1,3 @@
+SUBDIR=	virtual
+
+.include <bsd.subdir.mk>
diff --git a/sys/gnu/dev/virtual/Makefile b/sys/gnu/dev/virtual/Makefile
new file mode 100644
index 0000000..fa7ed95
--- /dev/null
+++ b/sys/gnu/dev/virtual/Makefile
@@ -0,0 +1,3 @@
+SUBDIR=	vmware
+
+.include <bsd.subdir.mk>
diff --git a/sys/gnu/dev/virtual/vmware/Makefile b/sys/gnu/dev/virtual/vmware/Makefile
new file mode 100644
index 0000000..05daf94
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/Makefile
@@ -0,0 +1,3 @@
+SUBDIR=	vmmemctl
+
+.include <bsd.subdir.mk>
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/COPYING b/sys/gnu/dev/virtual/vmware/vmmemctl/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/COPYING
@@ -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.
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/Makefile b/sys/gnu/dev/virtual/vmware/vmmemctl/Makefile
new file mode 100644
index 0000000..3490bdf
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/Makefile
@@ -0,0 +1,13 @@
+KMOD=	vmmemctl
+
+SRCS=	os.c vmballoon.c
+
+.if $(MACHINE_ARCH) == "x86_64"
+SRCS+=	backdoorGcc64.c
+.else
+SRCS+=	backdoorGcc32.c
+.endif
+
+CFLAGS+=-I${.CURDIR}/../../../../../dev/virtual/vmware/shared
+
+.include <bsd.kmod.mk>
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/README b/sys/gnu/dev/virtual/vmware/vmmemctl/README
new file mode 100644
index 0000000..67c2094
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/README
@@ -0,0 +1,12 @@
+The files in this directory are the source files for the VMware
+Memory Control driver.  The driver will be built automatically
+by the VMware Tools install script.  If you wish to build the
+driver by hand, run the following commands:
+
+	make
+        make install
+
+from this directory.  The module 'vmmemctl.ko' will be built and
+installed in /modules.
+
+If you have any problems or questions, send mail to support@vmware.com
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/backdoor.h b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoor.h
new file mode 100644
index 0000000..d4a1c22
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoor.h
@@ -0,0 +1,46 @@
+/*********************************************************
+ * Copyright (C) 1999 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * backdoor.h --
+ *
+ *    First layer of the internal communication channel between guest
+ *    applications and vmware
+ */
+
+#ifndef _BACKDOOR_H_
+#define _BACKDOOR_H_
+
+#include "vm_basic_types.h"
+#include "vm_assert.h"
+
+#include "backdoor_types.h"
+
+void
+Backdoor(Backdoor_proto *bp); // IN/OUT
+
+void
+Backdoor_InOut(Backdoor_proto *bp); // IN/OUT
+
+void
+Backdoor_HbOut(Backdoor_proto_hb *bp); // IN/OUT
+
+void
+Backdoor_HbIn(Backdoor_proto_hb *bp); // IN/OUT
+
+#endif /* _BACKDOOR_H_ */
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc32.c b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc32.c
new file mode 100644
index 0000000..da5a13b
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc32.c
@@ -0,0 +1,220 @@
+/*********************************************************
+ * 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
+ *
+ *********************************************************/
+
+/*
+ * backdoorGcc32.c --
+ *
+ *      Implements the real work for guest-side backdoor for GCC, 32-bit
+ *      target (supports inline ASM, GAS syntax). The asm sections are marked
+ *      volatile since vmware can change the registers content without the
+ *      compiler knowing it.
+ *
+ *      XXX
+ *      I tried to write this more cleanly, but:
+ *        - There is no way to specify an "ebp" constraint
+ *        - "ebp" is ignored when specified as cloberred register
+ *        - gas barfs when there is more than 10 operands
+ *        - gas 2.7.2.3, depending on the order of the operands, can
+ *          mis-assemble without any warning
+ *      --hpreg
+ *
+ *      Note that the problems with gas noted above might longer be relevant
+ *      now that we've upgraded most of our compiler versions.
+ *      --rrdharan
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "backdoor.h"
+#include "backdoorInt.h"
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * Backdoor_InOut --
+ *
+ *      Send a low-bandwidth basic request (16 bytes) to vmware, and return its
+ *      reply (24 bytes).
+ *
+ * Results:
+ *      Host-side response returned in bp IN/OUT parameter.
+ *
+ * Side effects:
+ *      Pokes the backdoor.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
+{
+   uint32 dummy;
+
+   __asm__ __volatile__(
+#ifdef __PIC__
+        "pushl %%ebx"           "\n\t"
+#endif
+        "pushl %%eax"           "\n\t"
+        "movl 20(%%eax), %%edi" "\n\t"
+        "movl 16(%%eax), %%esi" "\n\t"
+        "movl 12(%%eax), %%edx" "\n\t"
+        "movl  8(%%eax), %%ecx" "\n\t"
+        "movl  4(%%eax), %%ebx" "\n\t"
+        "movl   (%%eax), %%eax" "\n\t"
+        "inl %%dx, %%eax"       "\n\t"
+        "xchgl %%eax, (%%esp)"  "\n\t"
+        "movl %%edi, 20(%%eax)" "\n\t"
+        "movl %%esi, 16(%%eax)" "\n\t"
+        "movl %%edx, 12(%%eax)" "\n\t"
+        "movl %%ecx,  8(%%eax)" "\n\t"
+        "movl %%ebx,  4(%%eax)" "\n\t"
+        "popl          (%%eax)" "\n\t"
+#ifdef __PIC__
+        "popl %%ebx"            "\n\t"
+#endif
+      : "=a" (dummy)
+      : "0" (myBp)
+      /*
+       * vmware can modify the whole VM state without the compiler knowing
+       * it. So far it does not modify EFLAGS. --hpreg
+       */
+      :
+#ifndef __PIC__
+        "ebx",
+#endif
+        "ecx", "edx", "esi", "edi", "memory"
+   );
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * BackdoorHbIn  --
+ * BackdoorHbOut --
+ *
+ *      Send a high-bandwidth basic request to vmware, and return its
+ *      reply.
+ *
+ * Results:
+ *      Host-side response returned in bp IN/OUT parameter.
+ *
+ * Side-effects:
+ *      Pokes the high-bandwidth backdoor port.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
+{
+   uint32 dummy;
+
+   __asm__ __volatile__(
+#ifdef __PIC__
+        "pushl %%ebx"           "\n\t"
+#endif
+        "pushl %%ebp"           "\n\t"
+
+        "pushl %%eax"           "\n\t"
+        "movl 24(%%eax), %%ebp" "\n\t"
+        "movl 20(%%eax), %%edi" "\n\t"
+        "movl 16(%%eax), %%esi" "\n\t"
+        "movl 12(%%eax), %%edx" "\n\t"
+        "movl  8(%%eax), %%ecx" "\n\t"
+        "movl  4(%%eax), %%ebx" "\n\t"
+        "movl   (%%eax), %%eax" "\n\t"
+        "cld"                   "\n\t"
+        "rep; insb"             "\n\t"
+        "xchgl %%eax, (%%esp)"  "\n\t"
+        "movl %%ebp, 24(%%eax)" "\n\t"
+        "movl %%edi, 20(%%eax)" "\n\t"
+        "movl %%esi, 16(%%eax)" "\n\t"
+        "movl %%edx, 12(%%eax)" "\n\t"
+        "movl %%ecx,  8(%%eax)" "\n\t"
+        "movl %%ebx,  4(%%eax)" "\n\t"
+        "popl          (%%eax)" "\n\t"
+
+        "popl %%ebp"            "\n\t"
+#ifdef __PIC__
+        "popl %%ebx"            "\n\t"
+#endif
+      : "=a" (dummy)
+      : "0" (myBp)
+      /*
+       * vmware can modify the whole VM state without the compiler knowing
+       * it. --hpreg
+       */
+      :
+#ifndef __PIC__
+        "ebx",
+#endif
+        "ecx", "edx", "esi", "edi", "memory", "cc"
+   );
+}
+
+
+void
+BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
+{
+   uint32 dummy;
+
+   __asm__ __volatile__(
+#ifdef __PIC__
+        "pushl %%ebx"           "\n\t"
+#endif
+        "pushl %%ebp"           "\n\t"
+
+        "pushl %%eax"           "\n\t"
+        "movl 24(%%eax), %%ebp" "\n\t"
+        "movl 20(%%eax), %%edi" "\n\t"
+        "movl 16(%%eax), %%esi" "\n\t"
+        "movl 12(%%eax), %%edx" "\n\t"
+        "movl  8(%%eax), %%ecx" "\n\t"
+        "movl  4(%%eax), %%ebx" "\n\t"
+        "movl   (%%eax), %%eax" "\n\t"
+        "cld"                   "\n\t"
+        "rep; outsb"            "\n\t"
+        "xchgl %%eax, (%%esp)"  "\n\t"
+        "movl %%ebp, 24(%%eax)" "\n\t"
+        "movl %%edi, 20(%%eax)" "\n\t"
+        "movl %%esi, 16(%%eax)" "\n\t"
+        "movl %%edx, 12(%%eax)" "\n\t"
+        "movl %%ecx,  8(%%eax)" "\n\t"
+        "movl %%ebx,  4(%%eax)" "\n\t"
+        "popl          (%%eax)" "\n\t"
+
+        "popl %%ebp"            "\n\t"
+#ifdef __PIC__
+        "popl %%ebx"            "\n\t"
+#endif
+      : "=a" (dummy)
+      : "0" (myBp)
+      :
+#ifndef __PIC__
+        "ebx",
+#endif
+        "ecx", "edx", "esi", "edi", "memory", "cc"
+   );
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc64.c b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc64.c
new file mode 100644
index 0000000..4a7630c
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorGcc64.c
@@ -0,0 +1,229 @@
+/*********************************************************
+ * 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
+ *
+ *********************************************************/
+
+/*
+ * backdoorGcc64.c --
+ *
+ *      Implements the real work for guest-side backdoor for GCC, 64-bit
+ *      target (supports inline ASM, GAS syntax). The asm sections are marked
+ *      volatile since vmware can change the registers content without the
+ *      compiler knowing it.
+ *
+ *      See backdoorGCC32.c (from which this code was mostly copied) for
+ *      details on why the ASM is written this way. Also note that it might be
+ *      possible to write the asm blocks using the symbolic operand specifiers
+ *      in such a way that the same asm would generate correct code for both
+ *      32-bit and 64-bit targets, but I'm too lazy to figure it all out.
+ *      --rrdharan
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "backdoor.h"
+#include "backdoorInt.h"
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * Backdoor_InOut --
+ *
+ *      Send a low-bandwidth basic request (16 bytes) to vmware, and return its
+ *      reply (24 bytes).
+ *
+ * Results:
+ *      Host-side response returned in bp IN/OUT parameter.
+ *
+ * Side effects:
+ *      Pokes the backdoor.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
+{
+   uint64 dummy;
+
+   __asm__ __volatile__(
+#ifdef __APPLE__
+        /*
+         * Save %rbx on the stack because the Mac OS GCC doesn't want us to
+         * clobber it - it erroneously thinks %rbx is the PIC register.
+         * (Radar bug 7304232)
+         */
+        "pushq %%rbx"           "\n\t"
+#endif
+        "pushq %%rax"           "\n\t"
+        "movq 40(%%rax), %%rdi" "\n\t"
+        "movq 32(%%rax), %%rsi" "\n\t"
+        "movq 24(%%rax), %%rdx" "\n\t"
+        "movq 16(%%rax), %%rcx" "\n\t"
+        "movq  8(%%rax), %%rbx" "\n\t"
+        "movq   (%%rax), %%rax" "\n\t"
+        "inl %%dx, %%eax"       "\n\t"  /* NB: There is no inq instruction */
+        "xchgq %%rax, (%%rsp)"  "\n\t"
+        "movq %%rdi, 40(%%rax)" "\n\t"
+        "movq %%rsi, 32(%%rax)" "\n\t"
+        "movq %%rdx, 24(%%rax)" "\n\t"
+        "movq %%rcx, 16(%%rax)" "\n\t"
+        "movq %%rbx,  8(%%rax)" "\n\t"
+        "popq          (%%rax)" "\n\t"
+#ifdef __APPLE__
+        "popq %%rbx"            "\n\t"
+#endif
+      : "=a" (dummy)
+      : "0" (myBp)
+      /*
+       * vmware can modify the whole VM state without the compiler knowing
+       * it. So far it does not modify EFLAGS. --hpreg
+       */
+      :
+#ifndef __APPLE__
+      /* %rbx is unchanged at the end of the function on Mac OS. */
+      "rbx",
+#endif
+      "rcx", "rdx", "rsi", "rdi", "memory"
+   );
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * BackdoorHbIn  --
+ * BackdoorHbOut --
+ *
+ *      Send a high-bandwidth basic request to vmware, and return its
+ *      reply.
+ *
+ * Results:
+ *      Host-side response returned in bp IN/OUT parameter.
+ *
+ * Side-effects:
+ *      Pokes the high-bandwidth backdoor port.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
+{
+   uint32 dummy;
+
+   __asm__ __volatile__(
+        "pushq %%rbp"           "\n\t"
+#ifdef __APPLE__
+        /*
+         * Save %rbx on the stack because the Mac OS GCC doesn't want us to
+         * clobber it - it erroneously thinks %rbx is the PIC register.
+         * (Radar bug 7304232)
+         */
+        "pushq %%rbx"           "\n\t"
+#endif
+        "pushq %%rax"           "\n\t"
+        "movq 48(%%rax), %%rbp" "\n\t"
+        "movq 40(%%rax), %%rdi" "\n\t"
+        "movq 32(%%rax), %%rsi" "\n\t"
+        "movq 24(%%rax), %%rdx" "\n\t"
+        "movq 16(%%rax), %%rcx" "\n\t"
+        "movq  8(%%rax), %%rbx" "\n\t"
+        "movq   (%%rax), %%rax" "\n\t"
+        "cld"                   "\n\t"
+        "rep; insb"             "\n\t"
+        "xchgq %%rax, (%%rsp)"  "\n\t"
+        "movq %%rbp, 48(%%rax)" "\n\t"
+        "movq %%rdi, 40(%%rax)" "\n\t"
+        "movq %%rsi, 32(%%rax)" "\n\t"
+        "movq %%rdx, 24(%%rax)" "\n\t"
+        "movq %%rcx, 16(%%rax)" "\n\t"
+        "movq %%rbx,  8(%%rax)" "\n\t"
+        "popq          (%%rax)" "\n\t"
+#ifdef __APPLE__
+        "popq %%rbx"            "\n\t"
+#endif
+        "popq %%rbp"
+      : "=a" (dummy)
+      : "0" (myBp)
+      /*
+       * vmware can modify the whole VM state without the compiler knowing
+       * it. --hpreg
+       */
+      :
+#ifndef __APPLE__
+      /* %rbx is unchanged at the end of the function on Mac OS. */
+      "rbx",
+#endif
+      "rcx", "rdx", "rsi", "rdi", "memory", "cc"
+   );
+}
+
+
+void
+BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
+{
+   uint64 dummy;
+
+   __asm__ __volatile__(
+        "pushq %%rbp"           "\n\t"
+#ifdef __APPLE__
+        /*
+         * Save %rbx on the stack because the Mac OS GCC doesn't want us to
+         * clobber it - it erroneously thinks %rbx is the PIC register.
+         * (Radar bug 7304232)
+         */
+        "pushq %%rbx"           "\n\t"
+#endif
+        "pushq %%rax"           "\n\t"
+        "movq 48(%%rax), %%rbp" "\n\t"
+        "movq 40(%%rax), %%rdi" "\n\t"
+        "movq 32(%%rax), %%rsi" "\n\t"
+        "movq 24(%%rax), %%rdx" "\n\t"
+        "movq 16(%%rax), %%rcx" "\n\t"
+        "movq  8(%%rax), %%rbx" "\n\t"
+        "movq   (%%rax), %%rax" "\n\t"
+        "cld"                   "\n\t"
+        "rep; outsb"            "\n\t"
+        "xchgq %%rax, (%%rsp)"  "\n\t"
+        "movq %%rbp, 48(%%rax)" "\n\t"
+        "movq %%rdi, 40(%%rax)" "\n\t"
+        "movq %%rsi, 32(%%rax)" "\n\t"
+        "movq %%rdx, 24(%%rax)" "\n\t"
+        "movq %%rcx, 16(%%rax)" "\n\t"
+        "movq %%rbx,  8(%%rax)" "\n\t"
+        "popq          (%%rax)" "\n\t"
+#ifdef __APPLE__
+        "popq %%rbx"            "\n\t"
+#endif
+        "popq %%rbp"
+      : "=a" (dummy)
+      : "0" (myBp)
+      :
+#ifndef __APPLE__
+      /* %rbx is unchanged at the end of the function on Mac OS. */
+      "rbx",
+#endif
+      "rcx", "rdx", "rsi", "rdi", "memory", "cc"
+   );
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorInt.h b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorInt.h
new file mode 100644
index 0000000..d85afa7
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoorInt.h
@@ -0,0 +1,26 @@
+/*********************************************************
+ * 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
+ *
+ *********************************************************/
+
+/*
+ * backdoorInt.h --
+ *
+ *      Internal function prototypes for the real backdoor work.
+ */
+
+void BackdoorHbIn(Backdoor_proto_hb *bp);
+void BackdoorHbOut(Backdoor_proto_hb *bp);
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/backdoor_balloon.h b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoor_balloon.h
new file mode 100644
index 0000000..7d06d08
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/backdoor_balloon.h
@@ -0,0 +1,39 @@
+/*********************************************************
+ * 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
+ *
+ *********************************************************/
+
+/*
+ * backdoor_balloon.h --
+ *
+ *    This file provides a wrapper for using the more generic backdoor library
+ *    together with the vmballoon-specific backdoor.
+ */
+
+#ifndef _BACKDOOR_BALLOON_H_
+#define _BACKDOOR_BALLOON_H_
+
+#include "backdoor.h"
+#include "balloon_def.h"
+
+static INLINE
+void Backdoor_Balloon(Backdoor_proto *myBp) {
+   myBp->in.ax.word = BALLOON_BDOOR_MAGIC;
+   myBp->in.dx.halfs.low = BALLOON_BDOOR_PORT;
+   Backdoor_InOut(myBp);
+}
+
+#endif /* _BACKDOOR_BALLOON_H_ */
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/balloon_def.h b/sys/gnu/dev/virtual/vmware/vmmemctl/balloon_def.h
new file mode 100644
index 0000000..20a4348
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/balloon_def.h
@@ -0,0 +1,83 @@
+/*********************************************************
+ * Copyright (C) 2000 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
+ *
+ *********************************************************/
+
+/*
+ * balloon_def.h --
+ *
+ *      Definitions for server "balloon" mechanism for reclaiming
+ *      physical memory from a VM.
+ */
+
+#ifndef _BALLOON_DEF_H
+#define _BALLOON_DEF_H
+
+#define INCLUDE_ALLOW_VMX
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_MODULE
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+/*
+ * constants
+ */
+
+/* backdoor port */
+#define BALLOON_BDOOR_PORT              (0x5670)
+#define BALLOON_BDOOR_MAGIC             (0x456c6d6f)
+
+/* backdoor command numbers */
+#define BALLOON_BDOOR_CMD_START         (0)
+#define BALLOON_BDOOR_CMD_TARGET        (1)
+#define BALLOON_BDOOR_CMD_LOCK          (2)
+#define BALLOON_BDOOR_CMD_UNLOCK        (3)
+#define BALLOON_BDOOR_CMD_GUEST_ID      (4)
+
+/* use config value for max balloon size */
+#define BALLOON_MAX_SIZE_USE_CONFIG     (0)
+
+/*
+ * Guest identities
+ *
+ *      Note : all values should fit in 32 bits
+ */
+typedef enum {
+   BALLOON_GUEST_UNKNOWN     = 0,
+   BALLOON_GUEST_LINUX       = 1,
+   BALLOON_GUEST_BSD         = 2,
+   BALLOON_GUEST_WINDOWS_NT4 = 3,
+   BALLOON_GUEST_WINDOWS_NT5 = 4,
+   BALLOON_GUEST_SOLARIS     = 5,
+   BALLOON_GUEST_MACOS       = 6,
+   BALLOON_GUEST_FROBOS      = 7,
+} BalloonGuest;
+
+/* error codes */
+#define BALLOON_SUCCESS                 (0)
+#define BALLOON_FAILURE                (-1)
+#define BALLOON_ERROR_CMD_INVALID       (1)
+#define BALLOON_ERROR_PPN_INVALID       (2)
+#define BALLOON_ERROR_PPN_LOCKED        (3)
+#define BALLOON_ERROR_PPN_UNLOCKED      (4)
+#define BALLOON_ERROR_PPN_PINNED        (5)
+#define BALLOON_ERROR_PPN_NOTNEEDED     (6)
+#define BALLOON_ERROR_RESET             (7)
+#define BALLOON_ERROR_BUSY              (8)
+
+#endif  /* _BALLOON_DEF_H */
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/dbllnklst.h b/sys/gnu/dev/virtual/vmware/vmmemctl/dbllnklst.h
new file mode 100644
index 0000000..d5fd802
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/dbllnklst.h
@@ -0,0 +1,290 @@
+/*********************************************************
+ * 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
+ *
+ *********************************************************/
+
+/*
+ * dbllnklst.h --
+ *
+ *    Double linked lists
+ */
+
+#ifndef _DBLLNKLST_H_
+#define _DBLLNKLST_H_
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_USERLEVEL
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+#define DblLnkLst_OffsetOf(type, field) ((intptr_t)&((type *)0)->field)
+
+#define DblLnkLst_Container(addr, type, field) \
+   ((type *)((char *)(addr) - DblLnkLst_OffsetOf(type, field)))
+
+#define DblLnkLst_ForEach(curr, head)                   \
+      for (curr = (head)->next; curr != (head); curr = (curr)->next)
+
+/* Safe from list element removal within loop body. */
+#define DblLnkLst_ForEachSafe(curr, nextElem, head)             \
+      for (curr = (head)->next, nextElem = (curr)->next;        \
+           curr != (head);                                      \
+           curr = nextElem, nextElem = (curr)->next)
+
+typedef struct DblLnkLst_Links {
+   struct DblLnkLst_Links *prev;
+   struct DblLnkLst_Links *next;
+} DblLnkLst_Links;
+
+
+/*
+ * Functions
+ *
+ * DblLnkLst_LinkFirst, DblLnkLst_LinkLast, and DblLnkLst_Swap are specific
+ * to anchored lists.  The rest are for both circular and anchored lists.
+ */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Init --
+ *
+ *    Initialize a member of a doubly linked list
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Init(DblLnkLst_Links *l) // IN
+{
+   l->prev = l->next = l;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Link --
+ *
+ *    Merge two doubly linked lists into one
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is DblLnkLst_Unlink)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Link(DblLnkLst_Links *l1, // IN
+               DblLnkLst_Links *l2) // IN
+{
+   DblLnkLst_Links *tmp;
+
+   (tmp      = l1->prev)->next = l2;
+   (l1->prev = l2->prev)->next = l1;
+    l2->prev = tmp                 ;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Unlink --
+ *
+ *    Split one doubly linked list into two
+ *
+ *    No check is performed: the caller must ensure that both members
+ *    belong to the same doubly linked list
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is DblLnkLst_Link)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
+                 DblLnkLst_Links *l2) // IN
+{
+   DblLnkLst_Links *tmp;
+
+   tmp       = l1->prev            ;
+   (l1->prev = l2->prev)->next = l1;
+   (l2->prev = tmp     )->next = l2;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Unlink1 --
+ *
+ *    Unlink an element from its list.
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
+{
+   DblLnkLst_Unlink(l, l->next);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * DblLnkLst_IsLinked --
+ *
+ *    Determines whether an element is linked with any other elements.
+ *
+ * Results:
+ *    TRUE if link is linked, FALSE otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+DblLnkLst_IsLinked(DblLnkLst_Links const *l) // IN
+{
+   /*
+    * A DblLnkLst_Links is either linked to itself (not linked) or linked to
+    * other elements in a list (linked).
+    */
+   return l->prev != l;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_LinkFirst --
+ *
+ *    Insert 'l' at the beginning of the list anchored at 'head'
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
+                    DblLnkLst_Links *l)    // IN
+{
+   DblLnkLst_Link(head->next, l);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_LinkLast --
+ *
+ *    Insert 'l' at the end of the list anchored at 'head'
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
+                   DblLnkLst_Links *l)    // IN
+{
+   DblLnkLst_Link(head, l);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DblLnkLst_Swap --
+ *
+ *    Swap all entries between the list anchored at 'head1' and the list
+ *    anchored at 'head2'.
+ *
+ *    The operation is commutative
+ *    The operation is inversible (its inverse is itself)
+ *
+ * Result
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+DblLnkLst_Swap(DblLnkLst_Links *head1,  // IN/OUT
+               DblLnkLst_Links *head2)  // IN/OUT
+{
+   DblLnkLst_Links const tmp = *head1;
+
+   if (DblLnkLst_IsLinked(head2)) {
+      (head1->prev = head2->prev)->next = head1;
+      (head1->next = head2->next)->prev = head1;
+   } else {
+      DblLnkLst_Init(head1);
+   }
+
+   if (tmp.prev != head1) {
+      (head2->prev = tmp.prev)->next = head2;
+      (head2->next = tmp.next)->prev = head2;
+   } else {
+      DblLnkLst_Init(head2);
+   }
+}
+
+
+#endif /* _DBLLNKLST_H_ */
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/os.c b/sys/gnu/dev/virtual/vmware/vmmemctl/os.c
new file mode 100644
index 0000000..7c0eafb
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/os.c
@@ -0,0 +1,757 @@
+/*********************************************************
+ * Copyright (C) 2000 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
+ *
+ *********************************************************/
+
+/*
+ * os.c --
+ *
+ *      Wrappers for FreeBSD system functions required by "vmmemctl".
+ */
+
+/*
+ * Compile-Time Options
+ */
+
+#define	OS_DISABLE_UNLOAD   0
+#define	OS_DEBUG            1
+
+/*
+ * Includes
+ */
+
+#include "vm_basic_types.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/sysctl.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_page2.h>
+#include <vm/vm_object.h>
+#include <vm/vm_param.h>
+#include <sys/vmmeter.h>
+
+#include <machine/stdarg.h>
+
+#include "os.h"
+#include "vmballoon.h"
+
+/*
+ * Types
+ */
+
+typedef struct {
+   /* system structures */
+   struct callout callout_handle;
+
+   /* termination flag */
+   volatile int stop;
+} os_timer;
+
+typedef struct {
+   unsigned long size;       /* bitmap size in bytes */
+   unsigned long *bitmap;    /* bitmap words */
+   unsigned int  hint;       /* start searching from this word */
+} os_pmap;
+
+typedef struct {
+   os_timer    timer;
+   os_pmap     pmap;
+   vm_object_t vmobject;     /* vm backing object */
+} os_state;
+
+MALLOC_DEFINE(M_VMMEMCTL, BALLOON_NAME, "vmmemctl metadata");
+
+/*
+ * Globals
+ */
+
+static os_state global_state;
+
+static void vmmemctl_init_sysctl(void);
+static void vmmemctl_deinit_sysctl(void);
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_Malloc --
+ *
+ *      Allocates kernel memory.
+ *
+ * Results:
+ *      On success: Pointer to allocated memory
+ *      On failure: NULL
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void *
+OS_Malloc(size_t size) // IN
+{
+   return kmalloc(size, M_VMMEMCTL, M_NOWAIT);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_Free --
+ *
+ *      Free allocated kernel memory.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+OS_Free(void *ptr,   // IN
+        size_t size) // IN
+{
+   kfree(ptr, M_VMMEMCTL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_MemZero --
+ *
+ *      Fill a memory location with 0s.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+OS_MemZero(void *ptr,   // OUT
+           size_t size) // IN
+{
+   bzero(ptr, size);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_MemCopy --
+ *
+ *      Copy a memory portion into another location.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+OS_MemCopy(void *dest,      // OUT
+           const void *src, // IN
+           size_t size)     // IN
+{
+   memcpy(dest, src, size);
+}
+
+/* find first zero bit */
+static __inline__ unsigned long os_ffz(unsigned long word)
+{
+#ifdef __x86_64__
+   __asm__("bsfq %1,%0"
+           :"=r" (word)
+           :"r" (~word));
+#else
+   __asm__("bsfl %1,%0"
+           :"=r" (word)
+           :"r" (~word));
+#endif
+   return word;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_ReservedPageGetLimit --
+ *
+ *      Predict the maximum achievable balloon size.
+ *
+ * Results:
+ *      Total memory pages.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+unsigned long
+OS_ReservedPageGetLimit(void)
+{
+   return vmstats.v_page_count;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_ReservedPageGetPPN --
+ *
+ *      Convert a page handle (of a physical page previously reserved with
+ *      OS_ReservedPageAlloc()) to a ppn.
+ *
+ * Results:
+ *      The ppn.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+unsigned long
+OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
+{
+   return (((vm_page_t)handle)->phys_addr) >> PAGE_SHIFT;
+}
+
+
+static void
+os_pmap_alloc(os_pmap *p) // IN
+{
+   /* number of pages (div. 8) */
+   p->size = (vmstats.v_page_count + 7) / 8;
+
+   /*
+    * expand to nearest word boundary
+    * XXX: bitmap can be greater than total number of pages in system
+    */
+   p->size = (p->size + sizeof(unsigned long) - 1) &
+                         ~(sizeof(unsigned long) - 1);
+
+   p->bitmap = (unsigned long *)kmem_alloc(&kernel_map, p->size);
+}
+
+
+static void
+os_pmap_free(os_pmap *p) // IN
+{
+   kmem_free(&kernel_map, (vm_offset_t)p->bitmap, p->size);
+   p->size = 0;
+   p->bitmap = NULL;
+}
+
+
+static void
+os_pmap_init(os_pmap *p) // IN
+{
+   /* alloc bitmap for pages in system */
+   os_pmap_alloc(p);
+   if (!p->bitmap) {
+      p->size = 0;
+      p->bitmap = NULL;
+      return;
+   }
+
+   /* clear bitmap */
+   bzero(p->bitmap, p->size);
+   p->hint = 0;
+}
+
+
+static vm_pindex_t
+os_pmap_getindex(os_pmap *p) // IN
+{
+   int i;
+   unsigned long bitidx, wordidx;
+
+   /* start scanning from hint */
+   wordidx = p->hint;
+
+   /* scan bitmap for unset bit */
+   for (i=0; i < p->size/sizeof (unsigned long); i++) {
+
+      if (!p->bitmap[wordidx]) {
+         p->bitmap[wordidx] = 1;
+         p->hint = wordidx;
+         return (wordidx * sizeof(unsigned long) * 8);
+      }
+      else if (p->bitmap[wordidx] != ~0UL) {
+
+         /* find first zero bit */
+         bitidx = os_ffz(p->bitmap[wordidx]);
+         p->bitmap[wordidx] |= (1<<bitidx);
+         p->hint = wordidx;
+         return (wordidx * sizeof(unsigned long) * 8) + bitidx;
+      }
+
+      wordidx = (wordidx+1) % (p->size/sizeof (unsigned long));
+   }
+
+   /* failed */
+   return (vm_pindex_t)-1;
+}
+
+
+static void
+os_pmap_putindex(os_pmap *p,         // IN
+                 vm_pindex_t pindex) // IN
+{
+   /* unset bit */
+   p->bitmap[pindex / (8*sizeof(unsigned long))] &=
+                             ~(1<<(pindex % (8*sizeof(unsigned long))));
+}
+
+
+static void
+os_kmem_free(vm_page_t page) // IN
+{
+   os_state *state = &global_state;
+   os_pmap *pmap = &state->pmap;
+
+   if ( !vm_page_lookup(state->vmobject, page->pindex) ) {
+      return;
+   }
+
+   os_pmap_putindex(pmap, page->pindex);
+   vm_page_free(page);
+}
+
+
+static vm_page_t
+os_kmem_alloc(int alloc_normal_failed) // IN
+{
+   vm_page_t page;
+   vm_pindex_t pindex;
+   os_state *state = &global_state;
+   os_pmap *pmap = &state->pmap;
+
+   pindex = os_pmap_getindex(pmap);
+   if (pindex == (vm_pindex_t)-1) {
+      return NULL;
+   }
+
+   /*
+    * BSD's page allocator does not support flags that are similar to
+    * KM_NOSLEEP and KM_SLEEP in Solaris. The main page allocation function
+    * vm_page_alloc() does not sleep ever. It just returns NULL when it
+    * cannot find a free (or cached-and-clean) page. Therefore, we use
+    * VM_ALLOC_NORMAL and VM_ALLOC_SYSTEM loosely to mean KM_NOSLEEP
+    * and KM_SLEEP respectively.
+    */
+   vm_object_hold(state->vmobject);
+   if (alloc_normal_failed) {
+      page = vm_page_alloc(state->vmobject, pindex, VM_ALLOC_SYSTEM);
+   } else {
+      page = vm_page_alloc(state->vmobject, pindex, VM_ALLOC_NORMAL);
+   }
+   vm_object_drop(state->vmobject);
+
+   if (!page) {
+      os_pmap_putindex(pmap, pindex);
+   }
+
+   return page;
+}
+
+
+static void
+os_balloonobject_delete(void)
+{
+   vm_object_deallocate(global_state.vmobject);
+}
+
+
+static void
+os_balloonobject_create(void)
+{
+   global_state.vmobject = vm_object_allocate(OBJT_DEFAULT,
+                  OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS));
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_ReservedPageAlloc --
+ *
+ *      Reserve a physical page for the exclusive use of this driver.
+ *
+ * Results:
+ *      On success: A valid page handle that can be passed to OS_ReservedPageGetPPN()
+ *                  or OS_ReservedPageFree().
+ *      On failure: PAGE_HANDLE_INVALID
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+PageHandle
+OS_ReservedPageAlloc(int canSleep) // IN
+{
+   vm_page_t page;
+
+   page = os_kmem_alloc(canSleep);
+   if (page == NULL) {
+      return PAGE_HANDLE_INVALID;
+   }
+
+   return (PageHandle)page;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_ReservedPageFree --
+ *
+ *      Unreserve a physical page previously reserved with OS_ReservedPageAlloc().
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+OS_ReservedPageFree(PageHandle handle) // IN: A valid page handle
+{
+   os_kmem_free((vm_page_t)handle);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * OS_Yield --
+ *
+ *      Yield the CPU, if needed.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+OS_Yield(void)
+{
+   /* Do nothing. */
+}
+
+
+/*
+ * vmmemctl_poll -
+ *
+ *      Calls Balloon_QueryAndExecute() to perform ballooning tasks and
+ *      then reschedules itself to be executed in BALLOON_POLL_PERIOD
+ *      seconds.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ */
+
+static void
+vmmemctl_poll(void *data) // IN
+{
+   os_timer *t = data;
+
+   if (!t->stop) {
+      /* invoke registered handler, rearm timer */
+      Balloon_QueryAndExecute();
+      callout_reset(&t->callout_handle, BALLOON_POLL_PERIOD * hz,
+	  vmmemctl_poll, t);
+   }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmmemctl_init --
+ *
+ *      Called at driver startup, initializes the balloon state and structures.
+ *
+ * Results:
+ *      On success: 0
+ *      On failure: standard error code
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmmemctl_init(void)
+{
+   os_state *state = &global_state;
+   os_timer *t = &state->timer;
+   os_pmap *pmap = &state->pmap;
+
+   if (!Balloon_Init(BALLOON_GUEST_BSD)) {
+      return EIO;
+   }
+
+   /* initialize timer state */
+   callout_init(&state->timer.callout_handle);
+
+   os_pmap_init(pmap);
+   os_balloonobject_create();
+
+   /* Set up and start polling */
+   callout_init(&t->callout_handle);
+   t->stop = FALSE;
+   callout_reset(&t->callout_handle, BALLOON_POLL_PERIOD * hz, vmmemctl_poll, t);
+
+   vmmemctl_init_sysctl();
+
+   /* log device load */
+   kprintf(BALLOON_NAME_VERBOSE " initialized\n");
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmmemctl_cleanup --
+ *
+ *      Called when the driver is terminating, cleanup initialized structures.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+vmmemctl_cleanup(void)
+{
+   os_state *state = &global_state;
+   os_timer *t = &state->timer;
+   os_pmap *pmap = &state->pmap;
+
+   vmmemctl_deinit_sysctl();
+
+   Balloon_Cleanup();
+
+   /* Stop polling */
+   t->stop = TRUE;
+   callout_stop(&t->callout_handle);
+
+   os_balloonobject_delete();
+   os_pmap_free(pmap);
+
+   /* log device unload */
+   kprintf(BALLOON_NAME_VERBOSE " unloaded\n");
+}
+
+
+/*
+ * Module Load/Unload Operations
+ */
+
+static int
+vmmemctl_load(module_t mod, // IN: Unused
+              int cmd,      // IN
+              void *arg)    // IN: Unused
+{
+   int err = 0;
+
+   switch (cmd) {
+   case MOD_LOAD:
+      err = vmmemctl_init();
+      break;
+
+    case MOD_UNLOAD:
+       if (OS_DISABLE_UNLOAD) {
+          /* prevent module unload */
+          err = EBUSY;
+       } else {
+          vmmemctl_cleanup();
+       }
+       break;
+
+   default:
+      err = EINVAL;
+      break;
+   }
+
+   return err;
+}
+
+
+static struct sysctl_oid *oid;
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmmemctl_sysctl --
+ *
+ *      This gets called to provide the sysctl output when requested.
+ *
+ * Results:
+ *      Error, if any
+ *
+ * Side effects:
+ *      Data is written into user-provided buffer
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+vmmemctl_sysctl(SYSCTL_HANDLER_ARGS)
+{
+   char buf[PAGE_SIZE];
+   size_t len = 0;
+   const BalloonStats *stats = Balloon_GetStats();
+
+   /* format size info */
+   len += ksnprintf(buf + len, sizeof(buf) - len,
+                   "target:             %8d pages\n"
+                   "current:            %8d pages\n",
+                   stats->nPagesTarget,
+                   stats->nPages);
+
+   /* format rate info */
+   len += ksnprintf(buf + len, sizeof(buf) - len,
+                   "rateNoSleepAlloc:   %8d pages/sec\n"
+                   "rateSleepAlloc:     %8d pages/sec\n"
+                   "rateFree:           %8d pages/sec\n",
+                   stats->rateNoSleepAlloc,
+                   stats->rateAlloc,
+                   stats->rateFree);
+
+   len += ksnprintf(buf + len, sizeof(buf) - len,
+                   "\n"
+                   "timer:              %8u\n"
+                   "start:              %8u (%4u failed)\n"
+                   "guestType:          %8u (%4u failed)\n"
+                   "lock:               %8u (%4u failed)\n"
+                   "unlock:             %8u (%4u failed)\n"
+                   "target:             %8u (%4u failed)\n"
+                   "primNoSleepAlloc:   %8u (%4u failed)\n"
+                   "primCanSleepAlloc:  %8u (%4u failed)\n"
+                   "primFree:           %8u\n"
+                   "errAlloc:           %8u\n"
+                   "errFree:            %8u\n",
+                   stats->timer,
+                   stats->start, stats->startFail,
+                   stats->guestType, stats->guestTypeFail,
+                   stats->lock,  stats->lockFail,
+                   stats->unlock, stats->unlockFail,
+                   stats->target, stats->targetFail,
+                   stats->primAlloc[BALLOON_PAGE_ALLOC_NOSLEEP],
+                   stats->primAllocFail[BALLOON_PAGE_ALLOC_NOSLEEP],
+                   stats->primAlloc[BALLOON_PAGE_ALLOC_CANSLEEP],
+                   stats->primAllocFail[BALLOON_PAGE_ALLOC_CANSLEEP],
+                   stats->primFree,
+                   stats->primErrorPageAlloc,
+                   stats->primErrorPageFree);
+
+   return SYSCTL_OUT(req, buf, len + 1);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmmemctl_init_sysctl --
+ *
+ *      Init out sysctl, to be used for providing driver state.
+ *
+ * Results:
+ *      none
+ *
+ * Side effects:
+ *      Sn OID for a sysctl is registered
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+vmmemctl_init_sysctl(void)
+{
+   oid =  sysctl_add_oid(NULL, SYSCTL_STATIC_CHILDREN(_vm), OID_AUTO,
+                         BALLOON_NAME, CTLTYPE_STRING | CTLFLAG_RD,
+                         0, 0, vmmemctl_sysctl, "A",
+                         BALLOON_NAME_VERBOSE);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmmemctl_deinit_sysctl --
+ *
+ *      Undo vmmemctl_init_sysctl(). Remove the sysctl we installed.
+ *
+ * Results:
+ *      none
+ *
+ * Side effects:
+ *      Sn OID for a sysctl is unregistered
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+vmmemctl_deinit_sysctl(void)
+{
+   if (oid) {
+      sysctl_remove_oid(oid,1,0);
+   }
+}
+
+DEV_MODULE(vmmemctl, vmmemctl_load, NULL);
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/os.h b/sys/gnu/dev/virtual/vmware/vmmemctl/os.h
new file mode 100644
index 0000000..f27dc35
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/os.h
@@ -0,0 +1,56 @@
+/*********************************************************
+ * Copyright (C) 2000 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
+ *
+ *********************************************************/
+
+/*
+ * os.h --
+ *
+ *      Definitions for OS-specific wrapper functions required by "vmmemctl".
+ */
+
+#ifndef	OS_H
+#define	OS_H
+
+#include "vm_basic_types.h"
+#include "balloon_def.h"
+
+/*
+ * Types
+ */
+
+typedef uintptr_t PageHandle;
+
+#define PAGE_HANDLE_INVALID 0
+
+/*
+ * Operations
+ */
+
+extern void OS_MemZero(void *ptr, size_t size);
+extern void OS_MemCopy(void *dest, const void *src, size_t size);
+
+extern void *OS_Malloc(size_t size);
+extern void OS_Free(void *ptr, size_t size);
+
+extern void OS_Yield(void);
+
+extern unsigned long OS_ReservedPageGetLimit(void);
+extern unsigned long OS_ReservedPageGetPPN(PageHandle handle);
+extern PageHandle    OS_ReservedPageAlloc(int canSleep);
+extern void          OS_ReservedPageFree(PageHandle handle);
+
+#endif  /* OS_H */
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.c b/sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.c
new file mode 100644
index 0000000..8a2ab7e
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.c
@@ -0,0 +1,1240 @@
+/*********************************************************
+ * Copyright (C) 2000 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
+ *
+ *********************************************************/
+
+/*
+ * vmballoon.c --
+ *
+ *      VMware physical memory management driver for Unix-ish
+ *      (Linux, FreeBSD, Solaris, Mac OS) guests. The driver acts like
+ *      a "balloon" that can be inflated to reclaim physical pages by
+ *      reserving them in the guest and invalidating them in the
+ *      monitor, freeing up the underlying machine pages so they can
+ *      be allocated to other guests.  The balloon can also be
+ *      deflated to allow the guest to use more physical memory.
+ *      Higher level policies can control the sizes of balloons in VMs
+ *      in order to manage physical memory resources.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Compile-Time Options
+ */
+
+#define BALLOON_RATE_ADAPT      1
+
+#define BALLOON_DEBUG           1
+#define BALLOON_DEBUG_VERBOSE   0
+
+#define BALLOON_STATS
+
+/*
+ * Includes
+ */
+
+#include "os.h"
+#include "backdoor.h"
+#include "backdoor_balloon.h"
+#include "dbllnklst.h"
+#include "vmballoon.h"
+
+/*
+ * Constants
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define BALLOON_PROTOCOL_VERSION        2
+
+#define BALLOON_CHUNK_PAGES             1000
+
+#define BALLOON_NOSLEEP_ALLOC_MAX       16384
+
+#define BALLOON_RATE_ALLOC_MIN          512
+#define BALLOON_RATE_ALLOC_MAX          2048
+#define BALLOON_RATE_ALLOC_INC          16
+
+#define BALLOON_RATE_FREE_MIN           512
+#define BALLOON_RATE_FREE_MAX           16384
+#define BALLOON_RATE_FREE_INC           16
+
+#define BALLOON_ERROR_PAGES             16
+
+/*
+ * When guest is under memory pressure, use a reduced page allocation
+ * rate for next several cycles.
+ */
+#define SLOW_PAGE_ALLOCATION_CYCLES     4
+
+/*
+ * Move it to bora/public/balloon_def.h later, if needed. Note that
+ * BALLOON_PAGE_ALLOC_FAILURE is an internal error code used for
+ * distinguishing page allocation failures from monitor-backdoor errors.
+ * We use value 1000 because all monitor-backdoor error codes are < 1000.
+ */
+#define BALLOON_PAGE_ALLOC_FAILURE      1000
+
+/* Maximum number of page allocations without yielding processor */
+#define BALLOON_ALLOC_YIELD_THRESHOLD   1024
+
+
+/*
+ * Types
+ */
+
+typedef struct BalloonChunk {
+   PageHandle page[BALLOON_CHUNK_PAGES];
+   uint32 pageCount;
+   DblLnkLst_Links node;
+} BalloonChunk;
+
+typedef struct {
+   PageHandle page[BALLOON_ERROR_PAGES];
+   uint32 pageCount;
+} BalloonErrorPages;
+
+typedef struct {
+   /* sets of reserved physical pages */
+   DblLnkLst_Links chunks;
+   int nChunks;
+
+   /* transient list of non-balloonable pages */
+   BalloonErrorPages errors;
+
+   BalloonGuest guestType;
+
+   /* balloon size */
+   int nPages;
+   int nPagesTarget;
+
+   /* reset flag */
+   int resetFlag;
+
+   /* adjustment rates (pages per second) */
+   int rateAlloc;
+   int rateFree;
+
+   /* slowdown page allocations for next few cycles */
+   int slowPageAllocationCycles;
+
+   /* statistics */
+   BalloonStats stats;
+} Balloon;
+
+/*
+ * Globals
+ */
+
+static Balloon globalBalloon;
+
+/*
+ * Balloon operations
+ */
+static int  BalloonPageAlloc(Balloon *b, BalloonPageAllocType allocType);
+static int  BalloonPageFree(Balloon *b, int monitorUnlock);
+static int  BalloonAdjustSize(Balloon *b, uint32 target);
+static void BalloonReset(Balloon *b);
+
+/*
+ * Backdoor Operations
+ */
+static int BalloonMonitorStart(Balloon *b);
+static int BalloonMonitorGuestType(Balloon *b);
+static int BalloonMonitorGetTarget(Balloon *b, uint32 *nPages);
+static int BalloonMonitorLockPage(Balloon *b, PageHandle handle);
+static int BalloonMonitorUnlockPage(Balloon *b, PageHandle handle);
+
+/*
+ * Macros
+ */
+
+#ifdef  BALLOON_STATS
+#define STATS_INC(stat) (stat)++
+#else
+#define STATS_INC(stat)
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Balloon_GetStats --
+ *
+ *      Returns information about balloon state, including the current and
+ *      target size, rates for allocating and freeing pages, and statistics
+ *      about past activity.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+
+const BalloonStats *
+Balloon_GetStats(void)
+{
+   Balloon *b = &globalBalloon;
+   BalloonStats *stats = &b->stats;
+
+   /*
+    * Fill in additional information about size and rates, which is
+    * normally kept in the Balloon structure itself.
+    */
+   stats->nPages = b->nPages;
+   stats->nPagesTarget = b->nPagesTarget;
+   stats->rateNoSleepAlloc = BALLOON_NOSLEEP_ALLOC_MAX;
+   stats->rateAlloc = b->rateAlloc;
+   stats->rateFree = b->rateFree;
+
+   return stats;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonChunk_Create --
+ *
+ *      Creates a new BalloonChunk object capable of tracking
+ *      BALLOON_CHUNK_PAGES PPNs.
+ *
+ *      We do not bother to define two versions (NOSLEEP and CANSLEEP)
+ *      of OS_Malloc because Chunk_Create does not require a new page
+ *      often.
+ *
+ * Results:
+ *      On success: initialized BalloonChunk
+ *      On failure: NULL
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static BalloonChunk *
+BalloonChunk_Create(void)
+{
+   BalloonChunk *chunk;
+
+   /* allocate memory, fail if unable */
+   chunk = OS_Malloc(sizeof *chunk);
+   if (chunk == NULL) {
+      return NULL;
+   }
+
+   /* initialize */
+   OS_MemZero(chunk, sizeof *chunk);
+   DblLnkLst_Init(&chunk->node);
+
+   return chunk;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonChunk_Destroy --
+ *
+ *      Reclaims all storage associated with specified BalloonChunk.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BalloonChunk_Destroy(BalloonChunk *chunk) // IN
+{
+   /* reclaim storage */
+   OS_Free(chunk, sizeof *chunk);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Balloon_Deallocate --
+ *
+ *      Frees all allocated pages.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Balloon_Deallocate(Balloon *b) // IN
+{
+   unsigned int cnt = 0;
+
+   /* free all pages, skipping monitor unlock */
+   while (b->nChunks > 0) {
+      (void) BalloonPageFree(b, FALSE);
+      if (++cnt >= b->rateFree) {
+         cnt = 0;
+         OS_Yield();
+      }
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonReset --
+ *
+ *      Resets balloon "b" to empty state.  Frees all allocated pages
+ *      and attempts to reset contact with the monitor.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Schedules next execution of balloon timer handler.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BalloonReset(Balloon *b) // IN
+{
+   uint32 status;
+
+   /* free all pages, skipping monitor unlock */
+   Balloon_Deallocate(b);
+
+   /* send start command */
+   status = BalloonMonitorStart(b);
+   if (status == BALLOON_SUCCESS) {
+      /* clear flag */
+      b->resetFlag = 0;
+
+      /* report guest type */
+      (void) BalloonMonitorGuestType(b);
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Balloon_QueryAndExecute --
+ *
+ *      Contacts monitor via backdoor to obtain balloon size target,
+ *      and starts adjusting balloon size to achieve target by allocating
+ *      or deallocating pages. Resets balloon if requested by the monitor.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Balloon_QueryAndExecute(void)
+{
+   Balloon *b = &globalBalloon;
+   uint32 target = 0; // Silence compiler warning.
+   int status;
+
+   /* update stats */
+   STATS_INC(b->stats.timer);
+
+   /* reset, if specified */
+   if (b->resetFlag) {
+      BalloonReset(b);
+   }
+
+   /* contact monitor via backdoor */
+   status = BalloonMonitorGetTarget(b, &target);
+
+   /* decrement slowPageAllocationCycles counter */
+   if (b->slowPageAllocationCycles > 0) {
+      b->slowPageAllocationCycles--;
+   }
+
+   if (status == BALLOON_SUCCESS) {
+      /* update target, adjust size */
+      b->nPagesTarget = target;
+      (void) BalloonAdjustSize(b, target);
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonErrorPageStore --
+ *
+ *      Attempt to add "page" to list of non-balloonable pages
+ *      associated with "b".
+ *
+ * Results:
+ *      On success: BALLOON_SUCCESS
+ *      On failure: BALLOON_FAILURE (non-balloonable page list is already full)
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonErrorPageStore(Balloon *b,      // IN
+                      PageHandle page) // IN
+{
+   /* fail if list already full */
+   if (b->errors.pageCount >= BALLOON_ERROR_PAGES) {
+      return BALLOON_FAILURE;
+   }
+
+   /* add page to list */
+   b->errors.page[b->errors.pageCount++] = page;
+   STATS_INC(b->stats.primErrorPageAlloc);
+   return BALLOON_SUCCESS;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonErrorPagesFree --
+ *
+ *      Deallocates all pages on the list of non-balloonable pages
+ *      associated with "b".
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BalloonErrorPagesFree(Balloon *b) // IN
+{
+   unsigned int i;
+
+   /* free all non-balloonable "error" pages */
+   for (i = 0; i < b->errors.pageCount; i++) {
+      OS_ReservedPageFree(b->errors.page[i]);
+      b->errors.page[i] = PAGE_HANDLE_INVALID;
+      STATS_INC(b->stats.primErrorPageFree);
+   }
+   b->errors.pageCount = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonGetChunk --
+ *
+ *      Attempt to find a "chunk" with a free slot to store locked page.
+ *      Try to allocate new chunk if all existing chunks are full.
+ *
+ * Results:
+ *      Returns NULL on failure.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static BalloonChunk *
+BalloonGetChunk(Balloon *b)         // IN
+{
+   BalloonChunk *chunk;
+
+   /* Get first chunk from the list */
+   if (DblLnkLst_IsLinked(&b->chunks)) {
+      chunk = DblLnkLst_Container(b->chunks.next, BalloonChunk, node);
+      if (chunk->pageCount < BALLOON_CHUNK_PAGES) {
+         /* This chunk has free slots, use it */
+         return chunk;
+      }
+   }
+
+   /* create new chunk */
+   chunk = BalloonChunk_Create();
+   if (chunk != NULL) {
+      DblLnkLst_LinkFirst(&b->chunks, &chunk->node);
+
+      /* update stats */
+      b->nChunks++;
+   }
+
+   return chunk;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonPageStore --
+ *
+ *      Add "page" to the given "chunk".
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BalloonPageStore(BalloonChunk *chunk, PageHandle page)
+{
+   chunk->page[chunk->pageCount++] = page;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonPageAlloc --
+ *
+ *      Attempts to allocate a physical page, inflating balloon "b".
+ *      Informs monitor of PPN for allocated page via backdoor.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonPageAlloc(Balloon *b,                     // IN
+                 BalloonPageAllocType allocType) // IN
+{
+   PageHandle page;
+   BalloonChunk *chunk = NULL;
+   Bool locked;
+   int status;
+
+   /* allocate page, fail if unable */
+   do {
+      STATS_INC(b->stats.primAlloc[allocType]);
+
+      /*
+       * Attempts to allocate and reserve a physical page.
+       *
+       * If canSleep == 1, i.e., BALLOON_PAGE_ALLOC_CANSLEEP:
+       *      The allocation can wait (sleep) for page writeout (swap) by the guest.
+       * otherwise canSleep == 0, i.e., BALLOON_PAGE_ALLOC_NOSLEEP:
+       *      If allocation of a page requires disk writeout, then just fail. DON'T sleep.
+       *
+       * Returns the physical address of the allocated page, or 0 if error.
+       */
+      page = OS_ReservedPageAlloc(allocType);
+      if (page == PAGE_HANDLE_INVALID) {
+         STATS_INC(b->stats.primAllocFail[allocType]);
+         return BALLOON_PAGE_ALLOC_FAILURE;
+      }
+
+      /* Get the chunk to store allocated page. */
+      if (!chunk) {
+         chunk = BalloonGetChunk(b);
+         if (!chunk) {
+            OS_ReservedPageFree(page);
+            return BALLOON_PAGE_ALLOC_FAILURE;
+         }
+      }
+
+      /* inform monitor via backdoor */
+      status = BalloonMonitorLockPage(b, page);
+      locked = status == BALLOON_SUCCESS;
+      if (!locked) {
+         if (status == BALLOON_ERROR_RESET ||
+             status == BALLOON_ERROR_PPN_NOTNEEDED) {
+            OS_ReservedPageFree(page);
+            return status;
+         }
+
+         /* place on list of non-balloonable pages, retry allocation */
+         status = BalloonErrorPageStore(b, page);
+         if (status != BALLOON_SUCCESS) {
+            OS_ReservedPageFree(page);
+            return status;
+         }
+      }
+   } while (!locked);
+
+   /* track allocated page */
+   BalloonPageStore(chunk, page);
+
+   /* update balloon size */
+   b->nPages++;
+
+   return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonPageFree --
+ *
+ *      Attempts to deallocate a physical page, deflating balloon "b".
+ *      Informs monitor of PPN for deallocated page via backdoor if
+ *      "monitorUnlock" is specified.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonPageFree(Balloon *b,        // IN
+                int monitorUnlock) // IN
+{
+   DblLnkLst_Links *node, *next;
+   BalloonChunk *chunk = NULL;
+   PageHandle page;
+   int status;
+
+   DblLnkLst_ForEachSafe(node, next, &b->chunks) {
+      chunk = DblLnkLst_Container(node, BalloonChunk, node);
+      if (chunk->pageCount > 0) {
+         break;
+      }
+
+      /* destroy empty chunk */
+      DblLnkLst_Unlink1(node);
+      BalloonChunk_Destroy(chunk);
+      chunk = NULL;
+
+      /* update stats */
+      b->nChunks--;
+   }
+
+   if (!chunk) {
+      /* We could not find a single non-empty chunk. */
+      return BALLOON_FAILURE;
+   }
+
+   /* deallocate last page */
+   page = chunk->page[--chunk->pageCount];
+
+   /* inform monitor via backdoor */
+   if (monitorUnlock) {
+      status = BalloonMonitorUnlockPage(b, page);
+      if (status != BALLOON_SUCCESS) {
+         /* reset next pointer, fail */
+         chunk->pageCount++;
+         return status;
+      }
+   }
+
+   /* deallocate page */
+   OS_ReservedPageFree(page);
+   STATS_INC(b->stats.primFree);
+
+   /* update balloon size */
+   b->nPages--;
+
+   /* reclaim chunk, if empty */
+   if (chunk->pageCount == 0) {
+      /* destroy empty chunk */
+      DblLnkLst_Unlink1(&chunk->node);
+      BalloonChunk_Destroy(chunk);
+
+      /* update stats */
+      b->nChunks--;
+   }
+
+   return BALLOON_SUCCESS;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonInflate--
+ *
+ *      Attempts to allocate physical pages to inflate balloon.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonInflate(Balloon *b,    // IN
+               uint32 target) // IN
+{
+   unsigned int goal;
+   unsigned int rate;
+   unsigned int i;
+   unsigned int allocations = 0;
+   int status = 0;
+   BalloonPageAllocType allocType = BALLOON_PAGE_ALLOC_NOSLEEP;
+
+   /*
+    * First try NOSLEEP page allocations to inflate balloon.
+    *
+    * If we do not throttle nosleep allocations, we can drain all
+    * free pages in the guest quickly (if the balloon target is high).
+    * As a side-effect, draining free pages helps to inform (force)
+    * the guest to start swapping if balloon target is not met yet,
+    * which is a desired behavior. However, balloon driver can consume
+    * all available CPU cycles if too many pages are allocated in a
+    * second. Therefore, we throttle nosleep allocations even when
+    * the guest is not under memory pressure. OTOH, if we have already
+    * predicted that the guest is under memory pressure, then we
+    * slowdown page allocations considerably.
+    */
+
+   goal = target - b->nPages;
+   /*
+    * Start with no sleep allocation rate which may be higher
+    * than sleeping allocation rate.
+    */
+   rate = b->slowPageAllocationCycles ?
+                b->rateAlloc : BALLOON_NOSLEEP_ALLOC_MAX;
+
+   for (i = 0; i < goal; i++) {
+
+      status = BalloonPageAlloc(b, allocType);
+      if (status != BALLOON_SUCCESS) {
+         if (status != BALLOON_PAGE_ALLOC_FAILURE) {
+            /*
+             * Not a page allocation failure, stop this cycle.
+             * Maybe we'll get new target from the host soon.
+             */
+            break;
+         }
+
+         if (allocType == BALLOON_PAGE_ALLOC_CANSLEEP) {
+            /*
+             * CANSLEEP page allocation failed, so guest is under severe
+             * memory pressure. Quickly decrease allocation rate.
+             */
+            b->rateAlloc = MAX(b->rateAlloc / 2, BALLOON_RATE_ALLOC_MIN);
+            break;
+         }
+
+         /*
+          * NOSLEEP page allocation failed, so the guest is under memory
+          * pressure. Let us slow down page allocations for next few cycles
+          * so that the guest gets out of memory pressure. Also, if we
+          * already allocated b->rateAlloc pages, let's pause, otherwise
+          * switch to sleeping allocations.
+          */
+         b->slowPageAllocationCycles = SLOW_PAGE_ALLOCATION_CYCLES;
+
+         if (i >= b->rateAlloc)
+            break;
+
+         allocType = BALLOON_PAGE_ALLOC_CANSLEEP;
+         /* Lower rate for sleeping allocations. */
+         rate = b->rateAlloc;
+      }
+
+      if (++allocations > BALLOON_ALLOC_YIELD_THRESHOLD) {
+         OS_Yield();
+         allocations = 0;
+      }
+
+      if (i >= rate) {
+         /* We allocated enough pages, let's take a break. */
+         break;
+      }
+   }
+
+   /*
+    * We reached our goal without failures so try increasing
+    * allocation rate.
+    */
+   if (status == BALLOON_SUCCESS && i >= b->rateAlloc) {
+      unsigned int mult = i / b->rateAlloc;
+
+      b->rateAlloc = MIN(b->rateAlloc + mult * BALLOON_RATE_ALLOC_INC,
+                         BALLOON_RATE_ALLOC_MAX);
+   }
+
+   /* release non-balloonable pages, succeed */
+   BalloonErrorPagesFree(b);
+   return BALLOON_SUCCESS;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonDeflate --
+ *
+ *      Frees physical pages to deflate balloon.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonDeflate(Balloon *b,    // IN
+               uint32 target) // IN
+{
+   int status, i;
+   uint32 nFree = b->nPages - target;
+
+   /* limit deallocation rate */
+   nFree = MIN(nFree, b->rateFree);
+
+   /* free pages to reach target */
+   for (i = 0; i < nFree; i++) {
+      status = BalloonPageFree(b, TRUE);
+      if (status != BALLOON_SUCCESS) {
+         if (BALLOON_RATE_ADAPT) {
+            /* quickly decrease rate if error */
+            b->rateFree = MAX(b->rateFree / 2, BALLOON_RATE_FREE_MIN);
+         }
+         return status;
+      }
+   }
+
+   if (BALLOON_RATE_ADAPT) {
+      /* slowly increase rate if no errors */
+      b->rateFree = MIN(b->rateFree + BALLOON_RATE_FREE_INC,
+                        BALLOON_RATE_FREE_MAX);
+   }
+
+   return BALLOON_SUCCESS;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonAdjustSize --
+ *
+ *      Attempts to allocate or deallocate physical pages in order
+ *      to reach desired "target" size for balloon "b".
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonAdjustSize(Balloon *b,    // IN
+                  uint32 target) // IN
+{
+   if (b->nPages < target) {
+      return BalloonInflate(b, target);
+   } else if (b->nPages > target) {
+      return BalloonDeflate(b, target);
+   } else {
+      /* already at target */
+      return BALLOON_SUCCESS;
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonMonitorStart --
+ *
+ *      Attempts to contact monitor via backdoor to begin operation.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonMonitorStart(Balloon *b) // IN
+{
+   uint32 status, target;
+   Backdoor_proto bp;
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_START;
+   bp.in.size = BALLOON_PROTOCOL_VERSION;
+
+   /* invoke backdoor */
+   Backdoor_Balloon(&bp);
+
+   /* parse return values */
+   status = bp.out.ax.word;
+   target = bp.out.bx.word;
+
+   /* update stats */
+   STATS_INC(b->stats.start);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.startFail);
+   }
+
+   return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonMonitorGuestType --
+ *
+ *      Attempts to contact monitor and report guest OS identity.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonMonitorGuestType(Balloon *b) // IN
+{
+   uint32 status, target;
+   Backdoor_proto bp;
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_GUEST_ID;
+   bp.in.size = b->guestType;
+
+   /* invoke backdoor */
+   Backdoor_Balloon(&bp);
+
+   /* parse return values */
+   status = bp.out.ax.word;
+   target = bp.out.bx.word;
+
+   /* set flag if reset requested */
+   if (status == BALLOON_ERROR_RESET) {
+      b->resetFlag = 1;
+   }
+
+   /* update stats */
+   STATS_INC(b->stats.guestType);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.guestTypeFail);
+   }
+
+   return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonMonitorGetTarget --
+ *
+ *      Attempts to contact monitor via backdoor to obtain desired
+ *      balloon size.
+ *
+ *      Predicts the maximum achievable balloon size and sends it
+ *      to vmm => vmkernel via vEbx register.
+ *
+ *      OS_ReservedPageGetLimit() returns either predicted max balloon
+ *      pages or BALLOON_MAX_SIZE_USE_CONFIG. In the later scenario,
+ *      vmkernel uses global config options for determining a guest's max
+ *      balloon size. Note that older vmballoon drivers set vEbx to
+ *      BALLOON_MAX_SIZE_USE_CONFIG, i.e., value 0 (zero). So vmkernel
+ *      will fallback to config-based max balloon size estimation.
+ *
+ * Results:
+ *      If successful, sets "target" to value obtained from monitor,
+ *      and returns BALLOON_SUCCESS. Otherwise returns error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonMonitorGetTarget(Balloon *b,     // IN
+                         uint32 *target) // OUT
+{
+   Backdoor_proto bp;
+   unsigned long limit;
+   uint32 limit32;
+   uint32 status;
+
+   limit = OS_ReservedPageGetLimit();
+
+   /* Ensure limit fits in 32-bits */
+   limit32 = (uint32)limit;
+   if (limit32 != limit) {
+      return BALLOON_FAILURE;
+   }
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_TARGET;
+   bp.in.size = limit;
+
+   /* invoke backdoor */
+   Backdoor_Balloon(&bp);
+
+   /* parse return values */
+   status  = bp.out.ax.word;
+   *target = bp.out.bx.word;
+
+   /* set flag if reset requested */
+   if (status == BALLOON_ERROR_RESET) {
+      b->resetFlag = 1;
+   }
+
+   /* update stats */
+   STATS_INC(b->stats.target);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.targetFail);
+   }
+
+   return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonMonitorLockPage --
+ *
+ *      Attempts to contact monitor and add PPN corresponding to
+ *      the page handle to set of "balloon locked" pages.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonMonitorLockPage(Balloon *b,        // IN
+                        PageHandle handle) // IN
+{
+   unsigned long ppn;
+   uint32 ppn32;
+   uint32 status, target;
+   Backdoor_proto bp;
+
+   ppn = OS_ReservedPageGetPPN(handle);
+
+   /* Ensure PPN fits in 32-bits, i.e. guest memory is limited to 16TB. */
+   ppn32 = (uint32)ppn;
+   if (ppn32 != ppn) {
+      return BALLOON_ERROR_PPN_INVALID;
+   }
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_LOCK;
+   bp.in.size = ppn32;
+
+   /* invoke backdoor */
+   Backdoor_Balloon(&bp);
+
+   /* parse return values */
+   status = bp.out.ax.word;
+   target = bp.out.bx.word;
+
+   /* set flag if reset requested */
+   if (status == BALLOON_ERROR_RESET) {
+      b->resetFlag = 1;
+   }
+
+   /* update stats */
+   STATS_INC(b->stats.lock);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.lockFail);
+   }
+
+   return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BalloonMonitorUnlockPage --
+ *
+ *      Attempts to contact monitor and remove PPN corresponding to
+ *      the page handle from set of "balloon locked" pages.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+BalloonMonitorUnlockPage(Balloon *b,        // IN
+                          PageHandle handle) // IN
+{
+   unsigned long ppn;
+   uint32 ppn32;
+   uint32 status, target;
+   Backdoor_proto bp;
+
+   ppn = OS_ReservedPageGetPPN(handle);
+
+   /* Ensure PPN fits in 32-bits, i.e. guest memory is limited to 16TB. */
+   ppn32 = (uint32)ppn;
+   if (ppn32 != ppn) {
+      return BALLOON_ERROR_PPN_INVALID;
+   }
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_UNLOCK;
+   bp.in.size = ppn32;
+
+   /* invoke backdoor */
+   Backdoor_Balloon(&bp);
+
+   /* parse return values */
+   status = bp.out.ax.word;
+   target = bp.out.bx.word;
+
+   /* set flag if reset requested */
+   if (status == BALLOON_ERROR_RESET) {
+      b->resetFlag = 1;
+   }
+
+   /* update stats */
+   STATS_INC(b->stats.unlock);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.unlockFail);
+   }
+
+   return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Balloon_Init --
+ *
+ *      Initializes state oif the balloon.
+ *
+ * Results:
+ *      Returns TRUE on success (always).
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+Balloon_Init(BalloonGuest guestType)
+{
+   Balloon *b = &globalBalloon;
+
+   DblLnkLst_Init(&b->chunks);
+
+   b->guestType = guestType;
+
+   /* initialize rates */
+   b->rateAlloc = BALLOON_RATE_ALLOC_MAX;
+   b->rateFree  = BALLOON_RATE_FREE_MAX;
+
+   /* initialize reset flag */
+   b->resetFlag = TRUE;
+
+   return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Balloon_Cleanup --
+ *
+ *      Cleanup after ballooning.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Balloon_Cleanup(void)
+{
+   Balloon *b = &globalBalloon;
+
+   /*
+    * Deallocate all reserved memory, and reset connection with monitor.
+    * Reset connection before deallocating memory to avoid potential for
+    * additional spurious resets from guest touching deallocated pages.
+    */
+   BalloonMonitorStart(b);
+   Balloon_Deallocate(b);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.h b/sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.h
new file mode 100644
index 0000000..5b7ab37
--- /dev/null
+++ b/sys/gnu/dev/virtual/vmware/vmmemctl/vmballoon.h
@@ -0,0 +1,90 @@
+/*********************************************************
+ * Copyright (C) 2000 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
+ *
+ *********************************************************/
+
+/*
+ * vmballoon.h: Definitions and macros for vmballoon driver.
+ */
+
+#ifndef	VMBALLOON_H
+#define	VMBALLOON_H
+
+#include "vm_basic_types.h"
+
+#define BALLOON_NAME                    "vmmemctl"
+#define BALLOON_NAME_VERBOSE            "VMware memory control driver"
+
+#define BALLOON_POLL_PERIOD             1 /* sec */
+
+/*
+ * Page allocation flags
+ */
+typedef enum BalloonPageAllocType {
+   BALLOON_PAGE_ALLOC_NOSLEEP = 0,
+   BALLOON_PAGE_ALLOC_CANSLEEP = 1,
+   BALLOON_PAGE_ALLOC_TYPES_NR,	// total number of alloc types
+} BalloonPageAllocType;
+
+/*
+ * Types
+ */
+
+typedef struct {
+   /* current status */
+   uint32 nPages;
+   uint32 nPagesTarget;
+
+   /* adjustment rates */
+   uint32 rateNoSleepAlloc;
+   uint32 rateAlloc;
+   uint32 rateFree;
+
+   /* high-level operations */
+   uint32 timer;
+
+   /* primitives */
+   uint32 primAlloc[BALLOON_PAGE_ALLOC_TYPES_NR];
+   uint32 primAllocFail[BALLOON_PAGE_ALLOC_TYPES_NR];
+   uint32 primFree;
+   uint32 primErrorPageAlloc;
+   uint32 primErrorPageFree;
+
+   /* monitor operations */
+   uint32 lock;
+   uint32 lockFail;
+   uint32 unlock;
+   uint32 unlockFail;
+   uint32 target;
+   uint32 targetFail;
+   uint32 start;
+   uint32 startFail;
+   uint32 guestType;
+   uint32 guestTypeFail;
+} BalloonStats;
+
+/*
+ * Operations
+ */
+
+Bool Balloon_Init(BalloonGuest guestType);
+void Balloon_Cleanup(void);
+
+void Balloon_QueryAndExecute(void);
+
+const BalloonStats *Balloon_GetStats(void);
+
+#endif	/* VMBALLOON_H */
diff --git a/sys/platform/pc32/Makefile.inc b/sys/platform/pc32/Makefile.inc
index ccf5b31..f9a1733 100644
--- a/sys/platform/pc32/Makefile.inc
+++ b/sys/platform/pc32/Makefile.inc
@@ -2,8 +2,8 @@
 #
 
 DEV_SUPPORT=	acpica agp bridge crypto disk drm misc netif \
-		pccard powermng raid serial sound smbus usbmisc video \
-		virtual/virtio
+		pccard powermng raid serial smbus sound usbmisc video \
+		virtual/virtio virtual/vmware_tools
 
 SYSCONS_APM_SUPPORT=1
 BOOT0CFG_SUPPORT=1
diff --git a/sys/platform/pc32/conf/files b/sys/platform/pc32/conf/files
index 8a0f3ea..5724293 100644
--- a/sys/platform/pc32/conf/files
+++ b/sys/platform/pc32/conf/files
@@ -93,6 +93,7 @@ bf_enc.o				optional	crypto		\
 crypto/des/arch/i386/des_enc.S		optional	crypto
 crypto/des/des_ecb.c			optional	crypto
 crypto/des/des_setkey.c			optional	crypto
+gnu/dev/virtual/vmware/vmmemctl/backdoorGcc32.c optional vmmemctl
 
 ${OSACPI_MD_DIR}/OsdEnvironment.c	optional        acpi
 ${OSACPI_MD_DIR}/acpi_cpu_machdep.c	optional	acpi
diff --git a/sys/platform/pc64/Makefile.inc b/sys/platform/pc64/Makefile.inc
index d3bac8d..128df0d 100644
--- a/sys/platform/pc64/Makefile.inc
+++ b/sys/platform/pc64/Makefile.inc
@@ -2,8 +2,8 @@
 #
 
 DEV_SUPPORT=	acpica agp bridge crypto disk drm misc netif \
-		pccard powermng raid serial sound smbus usbmisc video \
-		virtual/virtio
+		pccard powermng raid serial smbus sound usbmisc video \
+		virtual/virtio virtual/vmware_tools
 
 #SYSCONS_APM_SUPPORT=1
 BOOT0CFG_SUPPORT=1
diff --git a/sys/platform/pc64/conf/files b/sys/platform/pc64/conf/files
index 0012fb2..4bd3552 100644
--- a/sys/platform/pc64/conf/files
+++ b/sys/platform/pc64/conf/files
@@ -85,6 +85,7 @@ dev/netif/ndis/if_ndis_pci.c		optional	ndis cardbus
 dev/netif/ndis/if_ndis_pci.c		optional	ndis pci
 dev/netif/ndis/if_ndis_usb.c		optional	ndis oldusb
 dev/netif/ndis/if_ndis_u4b.c		optional	ndis usb
+gnu/dev/virtual/vmware/vmmemctl/backdoorGcc64.c optional vmmemctl
 dev/misc/kbd/atkbd.c			optional	atkbd
 dev/misc/kbd/atkbdc.c			optional	atkbdc
 dev/misc/kbd/kbd.c			optional	atkbd
-- 
1.8.2.2

