Index: trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- trunk/src/VBox/VMM/HWACCM.cpp	(revision 9008)
+++ trunk/src/VBox/VMM/HWACCM.cpp	(revision 9021)
@@ -102,4 +102,5 @@
 
     pVM->hwaccm.s.fActive        = false;
+    pVM->hwaccm.s.fNestedPaging  = false;
 
     /* On first entry we'll sync everything. */
Index: trunk/src/VBox/VMM/HWACCMInternal.h
===================================================================
--- trunk/src/VBox/VMM/HWACCMInternal.h	(revision 9008)
+++ trunk/src/VBox/VMM/HWACCMInternal.h	(revision 9021)
@@ -138,4 +138,7 @@
     /** Set when hardware acceleration is allowed. */
     bool                        fAllowed;
+
+    /** Set if nested paging is enabled. */
+    bool                        fNestedPaging;
 
     /** HWACCM_CHANGED_* flags. */
@@ -214,6 +217,4 @@
         /** Set if we need to flush the TLB during the world switch. */
         bool                        fForceTLBFlush;
-        /** Set if nested paging is enabled. */
-        bool                        fNestedPaging;
 
         /* Id of the last cpu we were executing code on (NIL_RTCPUID for the first time) */
Index: trunk/src/VBox/VMM/PGM.cpp
===================================================================
--- trunk/src/VBox/VMM/PGM.cpp	(revision 9008)
+++ trunk/src/VBox/VMM/PGM.cpp	(revision 9021)
@@ -654,5 +654,4 @@
 
 
-#if 1/// @todo ndef RT_ARCH_AMD64
 /*
  * Shadow - 32-bit mode
@@ -730,5 +729,4 @@
 #undef PGM_SHW_NAME_GC_STR
 #undef PGM_SHW_NAME_R0_STR
-#endif /* !RT_ARCH_AMD64 */
 
 
@@ -850,4 +848,119 @@
 #define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
 #include "PGMGst.h"
+#include "PGMBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_BIG
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_BTH_NAME_GC_STR
+#undef PGM_BTH_NAME_R0_STR
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+#undef PGM_GST_NAME_GC_STR
+#undef PGM_GST_NAME_R0_STR
+
+#undef PGM_SHW_TYPE
+#undef PGM_SHW_NAME
+#undef PGM_SHW_NAME_GC_STR
+#undef PGM_SHW_NAME_R0_STR
+
+/*
+ * Shadow - Nested paging mode
+ */
+#define PGM_SHW_TYPE                PGM_TYPE_NESTED
+#define PGM_SHW_NAME(name)          PGM_SHW_NAME_NESTED(name)
+#define PGM_SHW_NAME_GC_STR(name)   PGM_SHW_NAME_GC_NESTED_STR(name)
+#define PGM_SHW_NAME_R0_STR(name)   PGM_SHW_NAME_R0_NESTED_STR(name)
+#include "PGMShw.h"
+
+/* Guest - real mode */
+#define PGM_GST_TYPE                PGM_TYPE_REAL
+#define PGM_GST_NAME(name)          PGM_GST_NAME_REAL(name)
+#define PGM_GST_NAME_GC_STR(name)   PGM_GST_NAME_GC_REAL_STR(name)
+#define PGM_GST_NAME_R0_STR(name)   PGM_GST_NAME_R0_REAL_STR(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_REAL(name)
+#define PGM_BTH_NAME_GC_STR(name)   PGM_BTH_NAME_GC_NESTED_REAL_STR(name)
+#define PGM_BTH_NAME_R0_STR(name)   PGM_BTH_NAME_R0_NESTED_REAL_STR(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PHYS
+#include "PGMBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_BTH_NAME_GC_STR
+#undef PGM_BTH_NAME_R0_STR
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+#undef PGM_GST_NAME_GC_STR
+#undef PGM_GST_NAME_R0_STR
+
+/* Guest - protected mode */
+#define PGM_GST_TYPE                PGM_TYPE_PROT
+#define PGM_GST_NAME(name)          PGM_GST_NAME_PROT(name)
+#define PGM_GST_NAME_GC_STR(name)   PGM_GST_NAME_GC_PROT_STR(name)
+#define PGM_GST_NAME_R0_STR(name)   PGM_GST_NAME_R0_PROT_STR(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_PROT(name)
+#define PGM_BTH_NAME_GC_STR(name)   PGM_BTH_NAME_GC_NESTED_PROT_STR(name)
+#define PGM_BTH_NAME_R0_STR(name)   PGM_BTH_NAME_R0_NESTED_PROT_STR(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PHYS
+#include "PGMBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_BTH_NAME_GC_STR
+#undef PGM_BTH_NAME_R0_STR
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+#undef PGM_GST_NAME_GC_STR
+#undef PGM_GST_NAME_R0_STR
+
+/* Guest - 32-bit mode */
+#define PGM_GST_TYPE                PGM_TYPE_32BIT
+#define PGM_GST_NAME(name)          PGM_GST_NAME_32BIT(name)
+#define PGM_GST_NAME_GC_STR(name)   PGM_GST_NAME_GC_32BIT_STR(name)
+#define PGM_GST_NAME_R0_STR(name)   PGM_GST_NAME_R0_32BIT_STR(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_32BIT(name)
+#define PGM_BTH_NAME_GC_STR(name)   PGM_BTH_NAME_GC_NESTED_32BIT_STR(name)
+#define PGM_BTH_NAME_R0_STR(name)   PGM_BTH_NAME_R0_NESTED_32BIT_STR(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
+#define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
+#include "PGMBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_BIG
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_BTH_NAME_GC_STR
+#undef PGM_BTH_NAME_R0_STR
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+#undef PGM_GST_NAME_GC_STR
+#undef PGM_GST_NAME_R0_STR
+
+/* Guest - PAE mode */
+#define PGM_GST_TYPE                PGM_TYPE_PAE
+#define PGM_GST_NAME(name)          PGM_GST_NAME_PAE(name)
+#define PGM_GST_NAME_GC_STR(name)   PGM_GST_NAME_GC_PAE_STR(name)
+#define PGM_GST_NAME_R0_STR(name)   PGM_GST_NAME_R0_PAE_STR(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_PAE(name)
+#define PGM_BTH_NAME_GC_STR(name)   PGM_BTH_NAME_GC_NESTED_PAE_STR(name)
+#define PGM_BTH_NAME_R0_STR(name)   PGM_BTH_NAME_R0_NESTED_PAE_STR(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PAE_PT
+#define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
+#include "PGMBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_BIG
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_BTH_NAME_GC_STR
+#undef PGM_BTH_NAME_R0_STR
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+#undef PGM_GST_NAME_GC_STR
+#undef PGM_GST_NAME_R0_STR
+
+/* Guest - AMD64 mode */
+#define PGM_GST_TYPE                PGM_TYPE_AMD64
+#define PGM_GST_NAME(name)          PGM_GST_NAME_AMD64(name)
+#define PGM_GST_NAME_GC_STR(name)   PGM_GST_NAME_GC_AMD64_STR(name)
+#define PGM_GST_NAME_R0_STR(name)   PGM_GST_NAME_R0_AMD64_STR(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_AMD64(name)
+#define PGM_BTH_NAME_GC_STR(name)   PGM_BTH_NAME_GC_NESTED_AMD64_STR(name)
+#define PGM_BTH_NAME_R0_STR(name)   PGM_BTH_NAME_R0_NESTED_AMD64_STR(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PAE_PT
+#define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
 #include "PGMBth.h"
 #undef BTH_PGMPOOLKIND_PT_FOR_BIG
@@ -2336,4 +2449,5 @@
         case PGMMODE_AMD64:
         case PGMMODE_AMD64_NX:  return PGM_TYPE_AMD64;
+        case PGMMODE_NESTED:    return PGM_TYPE_NESTED;
         default:
             AssertFatalMsgFailed(("pgmMode=%d\n", pgmMode));
@@ -2351,7 +2465,7 @@
 DECLINLINE(unsigned) pgmModeDataIndex(unsigned uShwType, unsigned uGstType)
 {
-    Assert(uShwType >= PGM_TYPE_32BIT && uShwType <= PGM_TYPE_AMD64);
+    Assert(uShwType >= PGM_TYPE_32BIT && uShwType <= PGM_TYPE_NESTED);
     Assert(uGstType >= PGM_TYPE_REAL  && uGstType <= PGM_TYPE_AMD64);
-    return (uShwType - PGM_TYPE_32BIT) * (PGM_TYPE_AMD64 - PGM_TYPE_32BIT + 1)
+    return (uShwType - PGM_TYPE_32BIT) * (PGM_TYPE_AMD64 - PGM_TYPE_REAL + 1)
          + (uGstType - PGM_TYPE_REAL);
 }
@@ -2375,9 +2489,9 @@
 /**
  * Calculates the max data index.
- * @returns The number of entries in the pagaing data array.
+ * @returns The number of entries in the paging data array.
  */
 DECLINLINE(unsigned) pgmModeDataMaxIndex(void)
 {
-    return pgmModeDataIndex(PGM_TYPE_AMD64, PGM_TYPE_AMD64) + 1;
+    return pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_AMD64) + 1;
 }
 
@@ -2460,6 +2574,42 @@
     pModeData->uShwType = PGM_TYPE_AMD64;
     pModeData->uGstType = PGM_TYPE_AMD64;
-    rc = PGM_SHW_NAME_AMD64(InitData)(      pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
-    rc = PGM_GST_NAME_AMD64(InitData)(      pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_SHW_NAME_AMD64(InitData)(       pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_GST_NAME_AMD64(InitData)(       pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_BTH_NAME_AMD64_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+
+    pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_REAL)];
+    pModeData->uShwType = PGM_TYPE_NESTED;
+    pModeData->uGstType = PGM_TYPE_REAL;
+    rc = PGM_SHW_NAME_NESTED(InitData)(      pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_GST_NAME_REAL(InitData)(        pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_BTH_NAME_NESTED_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+
+    pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGMMODE_PROTECTED)];
+    pModeData->uShwType = PGM_TYPE_NESTED;
+    pModeData->uGstType = PGM_TYPE_PROT;
+    rc = PGM_SHW_NAME_NESTED(InitData)(      pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_GST_NAME_PROT(InitData)(        pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_BTH_NAME_NESTED_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+
+    pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_32BIT)];
+    pModeData->uShwType = PGM_TYPE_NESTED;
+    pModeData->uGstType = PGM_TYPE_32BIT;
+    rc = PGM_SHW_NAME_NESTED(InitData)(      pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_GST_NAME_32BIT(InitData)(       pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_BTH_NAME_NESTED_32BIT(InitData)(pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+
+    pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_PAE)];
+    pModeData->uShwType = PGM_TYPE_NESTED;
+    pModeData->uGstType = PGM_TYPE_PAE;
+    rc = PGM_SHW_NAME_NESTED(InitData)(      pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_GST_NAME_PAE(InitData)(         pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_BTH_NAME_NESTED_PAE(InitData)(  pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+
+    pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_AMD64)];
+    pModeData->uShwType = PGM_TYPE_NESTED;
+    pModeData->uGstType = PGM_TYPE_AMD64;
+    rc = PGM_SHW_NAME_NESTED(InitData)(       pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_GST_NAME_AMD64(InitData)(        pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
+    rc = PGM_BTH_NAME_NESTED_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
 
     return VINF_SUCCESS;
Index: trunk/src/VBox/VMM/PGMInternal.h
===================================================================
--- trunk/src/VBox/VMM/PGMInternal.h	(revision 9008)
+++ trunk/src/VBox/VMM/PGMInternal.h	(revision 9021)
@@ -191,4 +191,5 @@
 #define PGM_TYPE_PAE        4
 #define PGM_TYPE_AMD64      5
+#define PGM_TYPE_NESTED     6
 /** @} */
 
@@ -197,5 +198,5 @@
  * @remark  ASSUMES certain order of the PGM_TYPE_* values.
  */
-#define PGM_WITH_PAGING(uType)  ((uType) >= PGM_TYPE_32BIT)
+#define PGM_WITH_PAGING(uType)  ((uType) >= PGM_TYPE_32BIT && (uType) != PGM_TYPE_NESTED)
 
 /** Macro for checking if the guest supports the NX bit.
@@ -203,5 +204,5 @@
  * @remark  ASSUMES certain order of the PGM_TYPE_* values.
  */
-#define PGM_WITH_NX(uType)  ((uType) >= PGM_TYPE_PAE)
+#define PGM_WITH_NX(uType)  ((uType) >= PGM_TYPE_PAE && (uType) != PGM_TYPE_NESTED)
 
 
@@ -1710,4 +1711,7 @@
 #define PGM_SHW_NAME_GC_AMD64_STR(name) "pgmGCShwAMD64" #name
 #define PGM_SHW_NAME_R0_AMD64_STR(name) "pgmR0ShwAMD64" #name
+#define PGM_SHW_NAME_NESTED(name)        PGM_CTX(pgm,ShwNested##name)
+#define PGM_SHW_NAME_GC_NESTED_STR(name) "pgmGCShwNested" #name
+#define PGM_SHW_NAME_R0_NESTED_STR(name) "pgmR0ShwNested" #name
 #define PGM_SHW_DECL(type, name)        PGM_CTX_DECL(type) PGM_SHW_NAME(name)
 #define PGM_SHW_PFN(name, pVM)          ((pVM)->pgm.s.PGM_CTX(pfn,Shw##name))
@@ -1723,4 +1727,10 @@
 #define PGM_BTH_NAME_AMD64_PROT(name)   PGM_CTX(pgm,BthAMD64Prot##name)
 #define PGM_BTH_NAME_AMD64_AMD64(name)  PGM_CTX(pgm,BthAMD64AMD64##name)
+#define PGM_BTH_NAME_NESTED_REAL(name)  PGM_CTX(pgm,BthNestedReal##name)
+#define PGM_BTH_NAME_NESTED_PROT(name)  PGM_CTX(pgm,BthNestedProt##name)
+#define PGM_BTH_NAME_NESTED_32BIT(name) PGM_CTX(pgm,BthNested32Bit##name)
+#define PGM_BTH_NAME_NESTED_PAE(name)   PGM_CTX(pgm,BthNestedPAE##name)
+#define PGM_BTH_NAME_NESTED_AMD64(name) PGM_CTX(pgm,BthNestedAMD64##name)
+
 #define PGM_BTH_NAME_GC_32BIT_REAL_STR(name)   "pgmGCBth32BitReal" #name
 #define PGM_BTH_NAME_GC_32BIT_PROT_STR(name)   "pgmGCBth32BitProt" #name
@@ -1731,4 +1741,9 @@
 #define PGM_BTH_NAME_GC_PAE_PAE_STR(name)      "pgmGCBthPAEPAE" #name
 #define PGM_BTH_NAME_GC_AMD64_AMD64_STR(name)  "pgmGCBthAMD64AMD64" #name
+#define PGM_BTH_NAME_GC_NESTED_REAL_STR(name)  "pgmGCBthNestedReal" #name
+#define PGM_BTH_NAME_GC_NESTED_PROT_STR(name)  "pgmGCBthNestedProt" #name
+#define PGM_BTH_NAME_GC_NESTED_32BIT_STR(name) "pgmGCBthNested32Bit" #name
+#define PGM_BTH_NAME_GC_NESTED_PAE_STR(name)   "pgmGCBthNestedPAE" #name
+#define PGM_BTH_NAME_GC_NESTED_AMD64_STR(name) "pgmGCBthNestedAMD64" #name
 #define PGM_BTH_NAME_R0_32BIT_REAL_STR(name)   "pgmR0Bth32BitReal" #name
 #define PGM_BTH_NAME_R0_32BIT_PROT_STR(name)   "pgmR0Bth32BitProt" #name
@@ -1740,4 +1755,10 @@
 #define PGM_BTH_NAME_R0_AMD64_PROT_STR(name)   "pgmR0BthAMD64Prot" #name
 #define PGM_BTH_NAME_R0_AMD64_AMD64_STR(name)  "pgmR0BthAMD64AMD64" #name
+#define PGM_BTH_NAME_R0_NESTED_REAL_STR(name)  "pgmR0BthNestedReal" #name
+#define PGM_BTH_NAME_R0_NESTED_PROT_STR(name)  "pgmR0BthNestedProt" #name
+#define PGM_BTH_NAME_R0_NESTED_32BIT_STR(name) "pgmR0BthNested32Bit" #name
+#define PGM_BTH_NAME_R0_NESTED_PAE_STR(name)   "pgmR0BthNestedPAE" #name
+#define PGM_BTH_NAME_R0_NESTED_AMD64_STR(name) "pgmR0BthNestedAMD64" #name
+
 #define PGM_BTH_DECL(type, name)        PGM_CTX_DECL(type) PGM_BTH_NAME(name)
 #define PGM_BTH_PFN(name, pVM)          ((pVM)->pgm.s.PGM_CTX(pfn,Bth##name))
Index: trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 9008)
+++ trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 9021)
@@ -215,4 +215,76 @@
 #undef PGM_SHW_TYPE
 #undef PGM_SHW_NAME
+
+/*
+ * Shadow - Nested paging mode
+ */
+#define PGM_SHW_TYPE                PGM_TYPE_NESTED
+#define PGM_SHW_NAME(name)          PGM_SHW_NAME_NESTED(name)
+#include "PGMAllShw.h"
+
+/* Guest - real mode */
+#define PGM_GST_TYPE                PGM_TYPE_REAL
+#define PGM_GST_NAME(name)          PGM_GST_NAME_REAL(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_REAL(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PHYS
+#include "PGMAllBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+
+/* Guest - protected mode */
+#define PGM_GST_TYPE                PGM_TYPE_PROT
+#define PGM_GST_NAME(name)          PGM_GST_NAME_PROT(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_PROT(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PHYS
+#include "PGMAllBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+
+/* Guest - 32-bit mode */
+#define PGM_GST_TYPE                PGM_TYPE_32BIT
+#define PGM_GST_NAME(name)          PGM_GST_NAME_32BIT(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_32BIT(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
+#define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
+#include "PGMAllBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_BIG
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+
+/* Guest - PAE mode */
+#define PGM_GST_TYPE                PGM_TYPE_PAE
+#define PGM_GST_NAME(name)          PGM_GST_NAME_PAE(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_PAE(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PAE_PT
+#define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
+#include "PGMAllBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_BIG
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+
+/* Guest - AMD64 mode */
+#define PGM_GST_TYPE                PGM_TYPE_AMD64
+#define PGM_GST_NAME(name)          PGM_GST_NAME_AMD64(name)
+#define PGM_BTH_NAME(name)          PGM_BTH_NAME_NESTED_AMD64(name)
+#define BTH_PGMPOOLKIND_PT_FOR_PT   PGMPOOLKIND_PAE_PT_FOR_PAE_PT
+#define BTH_PGMPOOLKIND_PT_FOR_BIG  PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
+#include "PGMAllBth.h"
+#undef BTH_PGMPOOLKIND_PT_FOR_BIG
+#undef BTH_PGMPOOLKIND_PT_FOR_PT
+#undef PGM_BTH_NAME
+#undef PGM_GST_TYPE
+#undef PGM_GST_NAME
+
+#undef PGM_SHW_TYPE
+#undef PGM_SHW_NAME
+
 #endif
 
@@ -433,23 +505,26 @@
     }
 
-    /*
-     * Next step is to verify if we protected this page for dirty bit tracking or for CSAM scanning
-     */
-    rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, NULL, NULL);
-    if (    rc == VERR_PAGE_NOT_PRESENT
-        ||  rc == VERR_PAGE_TABLE_NOT_PRESENT)
+    if (!HWACCMIsNestedPagingActive(pVM))
     {
         /*
-         * Page is not present in our page tables.
-         * Try to sync it!
-         */
-        Assert(X86_TRAP_PF_RW == X86_PTE_RW && X86_TRAP_PF_US == X86_PTE_US);
-        uint32_t uErr = fAccess & (X86_TRAP_PF_RW | X86_TRAP_PF_US);
-        rc = PGM_BTH_PFN(VerifyAccessSyncPage, pVM)(pVM, Addr, fPageGst, uErr);
-        if (rc != VINF_SUCCESS)
-            return rc;
-    }
-    else
-        AssertMsg(rc == VINF_SUCCESS, ("PGMShwGetPage %VGv failed with %Vrc\n", Addr, rc));
+        * Next step is to verify if we protected this page for dirty bit tracking or for CSAM scanning
+        */
+        rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, NULL, NULL);
+        if (    rc == VERR_PAGE_NOT_PRESENT
+            ||  rc == VERR_PAGE_TABLE_NOT_PRESENT)
+        {
+            /*
+            * Page is not present in our page tables.
+            * Try to sync it!
+            */
+            Assert(X86_TRAP_PF_RW == X86_PTE_RW && X86_TRAP_PF_US == X86_PTE_US);
+            uint32_t uErr = fAccess & (X86_TRAP_PF_RW | X86_TRAP_PF_US);
+            rc = PGM_BTH_PFN(VerifyAccessSyncPage, pVM)(pVM, Addr, fPageGst, uErr);
+            if (rc != VINF_SUCCESS)
+                return rc;
+        }
+        else
+            AssertMsg(rc == VINF_SUCCESS, ("PGMShwGetPage %VGv failed with %Vrc\n", Addr, rc));
+    }
 
 #if 0 /* def VBOX_STRICT; triggers too often now */
@@ -667,4 +742,6 @@
     int            rc;
 
+    Assert(!HWACCMIsNestedPagingActive(pVM));
+
     pPml4e = &pPGM->pHCPaePML4->a[iPml4e];
     if (    !pPml4e->n.u1Present
@@ -1351,4 +1428,5 @@
     STAM_PROFILE_STOP(&pVM->pgm.s.CTXMID(Stat,SyncCR3), a);
     return cErrors;
+    return 0;
 }
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 9008)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 9021)
@@ -44,20 +44,20 @@
 
 /* Filter out some illegal combinations of guest and shadow paging, so we can remove redundant checks inside functions. */
-#if      PGM_GST_TYPE == PGM_TYPE_PAE && PGM_SHW_TYPE != PGM_TYPE_PAE
+#if      PGM_GST_TYPE == PGM_TYPE_PAE && PGM_SHW_TYPE != PGM_TYPE_PAE && PGM_SHW_TYPE != PGM_TYPE_NESTED
 # error "Invalid combination; PAE guest implies PAE shadow"
 #endif
 
 #if     (PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT) \
-    && !(PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE || PGM_SHW_TYPE == PGM_TYPE_AMD64)
+    && !(PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE || PGM_SHW_TYPE == PGM_TYPE_AMD64 || PGM_SHW_TYPE == PGM_TYPE_NESTED)
 # error "Invalid combination; real or protected mode without paging implies 32 bits or PAE shadow paging."
 #endif
 
 #if     (PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_PAE) \
-    && !(PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE)
+    && !(PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE || PGM_SHW_TYPE == PGM_TYPE_NESTED)
 # error "Invalid combination; 32 bits guest paging or PAE implies 32 bits or PAE shadow paging."
 #endif
 
-#if    (PGM_GST_TYPE == PGM_TYPE_AMD64 && PGM_SHW_TYPE != PGM_TYPE_AMD64)
-    || (PGM_SHW_TYPE == PGM_TYPE_AMD64 && PGM_GST_TYPE != PGM_TYPE_AMD64)
+#if    (PGM_GST_TYPE == PGM_TYPE_AMD64 && PGM_SHW_TYPE != PGM_TYPE_AMD64 && PGM_SHW_TYPE != PGM_TYPE_NESTED) \
+    || (PGM_SHW_TYPE == PGM_TYPE_AMD64 && PGM_GST_TYPE != PGM_TYPE_AMD64 && PGM_GST_TYPE != PGM_TYPE_PROT)
 # error "Invalid combination; AMD64 guest implies AMD64 shadow and vice versa"
 #endif
@@ -78,5 +78,6 @@
 PGM_BTH_DECL(int, Trap0eHandler)(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
 {
-#if PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT || PGM_GST_TYPE == PGM_TYPE_PAE || PGM_GST_TYPE == PGM_TYPE_AMD64
+#if (PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT || PGM_GST_TYPE == PGM_TYPE_PAE || PGM_GST_TYPE == PGM_TYPE_AMD64) \
+    && PGM_SHW_TYPE != PGM_TYPE_NESTED
 
 # if PGM_SHW_TYPE == PGM_TYPE_PAE && PGM_GST_TYPE != PGM_TYPE_PAE
@@ -846,7 +847,6 @@
 PGM_BTH_DECL(int, InvalidatePage)(PVM pVM, RTGCUINTPTR GCPtrPage)
 {
-#if    PGM_GST_TYPE == PGM_TYPE_32BIT \
-    || PGM_GST_TYPE == PGM_TYPE_PAE \
-    || PGM_GST_TYPE == PGM_TYPE_AMD64
+#if    PGM_WITH_PAGING(PGM_GST_TYPE) \
+    && PGM_SHW_TYPE != PGM_TYPE_NESTED
     int rc;
 
@@ -1418,6 +1418,7 @@
     LogFlow(("SyncPage: GCPtrPage=%VGv cPages=%d uErr=%#x\n", GCPtrPage, cPages, uErr));
 
-#if    PGM_GST_TYPE == PGM_TYPE_32BIT \
-    || PGM_GST_TYPE == PGM_TYPE_PAE
+#if    (PGM_GST_TYPE == PGM_TYPE_32BIT \
+    ||  PGM_GST_TYPE == PGM_TYPE_PAE) \
+    && PGM_SHW_TYPE != PGM_TYPE_NESTED
 
 # if PGM_WITH_NX(PGM_GST_TYPE)
@@ -1660,5 +1661,6 @@
     return VINF_PGM_SYNCPAGE_MODIFIED_PDE;
 
-#elif PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT
+#elif (PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT) \
+      && PGM_SHW_TYPE != PGM_TYPE_NESTED
 
 # ifdef PGM_SYNC_N_PAGES
@@ -2091,6 +2093,7 @@
     LogFlow(("SyncPT: GCPtrPage=%VGv\n", GCPtrPage));
 
-#if    PGM_GST_TYPE == PGM_TYPE_32BIT \
-    || PGM_GST_TYPE == PGM_TYPE_PAE
+#if   (   PGM_GST_TYPE == PGM_TYPE_32BIT \
+       || PGM_GST_TYPE == PGM_TYPE_PAE) \
+    && PGM_SHW_TYPE != PGM_TYPE_NESTED
 
     /*
@@ -2444,5 +2447,6 @@
     return rc;
 
-#elif PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT
+#elif (PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT) \
+    && PGM_SHW_TYPE != PGM_TYPE_NESTED
 
     int     rc     = VINF_SUCCESS;
@@ -2519,5 +2523,7 @@
 PGM_BTH_DECL(int, PrefetchPage)(PVM pVM, RTGCUINTPTR GCPtrPage)
 {
-#if (PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT || PGM_GST_TYPE == PGM_TYPE_PAE) && PGM_SHW_TYPE != PGM_TYPE_AMD64
+    Assert(!HWACCMIsNestedPagingActive(pVM));
+#if (PGM_GST_TYPE == PGM_TYPE_32BIT || PGM_GST_TYPE == PGM_TYPE_REAL || PGM_GST_TYPE == PGM_TYPE_PROT || PGM_GST_TYPE == PGM_TYPE_PAE) \
+    && PGM_SHW_TYPE != PGM_TYPE_AMD64 && PGM_SHW_TYPE != PGM_TYPE_NESTED
     /*
      * Check that all Guest levels thru the PDE are present, getting the
@@ -2596,5 +2602,7 @@
     LogFlow(("VerifyAccessSyncPage: GCPtrPage=%VGv fPage=%#x uErr=%#x\n", GCPtrPage, fPage, uErr));
 
-#if (PGM_GST_TYPE == PGM_TYPE_32BIT ||  PGM_GST_TYPE == PGM_TYPE_REAL ||  PGM_GST_TYPE == PGM_TYPE_PROT || PGM_GST_TYPE == PGM_TYPE_PAE) && PGM_SHW_TYPE != PGM_TYPE_AMD64
+    Assert(!HWACCMIsNestedPagingActive(pVM));
+#if (PGM_GST_TYPE == PGM_TYPE_32BIT ||  PGM_GST_TYPE == PGM_TYPE_REAL ||  PGM_GST_TYPE == PGM_TYPE_PROT || PGM_GST_TYPE == PGM_TYPE_PAE) \
+    && PGM_SHW_TYPE != PGM_TYPE_AMD64 && PGM_SHW_TYPE != PGM_TYPE_NESTED
 
 # ifndef IN_RING0
@@ -2751,4 +2759,9 @@
 PGM_BTH_DECL(int, SyncCR3)(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal)
 {
+#if PGM_SHW_TYPE == PGM_TYPE_NESTED
+    /* @todo check if this is really necessary */
+    HWACCMFlushTLB(pVM);
+    return VINF_SUCCESS;
+#else
     if (VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3))
         fGlobal = true; /* Change this CR3 reload to be a global one. */
@@ -3111,10 +3124,11 @@
     return VINF_SUCCESS;
 
-#elif PGM_GST_TYPE == PGM_TYPE_AMD64
+# elif PGM_GST_TYPE == PGM_TYPE_AMD64
 //# error not implemented
     return VERR_INTERNAL_ERROR;
-#else /* guest real and protected mode */
+# else /* guest real and protected mode */
     return VINF_SUCCESS;
-#endif
+# endif
+#endif /* PGM_SHW_TYPE != PGM_TYPE_NESTED */
 }
 
@@ -3159,4 +3173,7 @@
 PGM_BTH_DECL(unsigned, AssertCR3)(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb)
 {
+#if PGM_SHW_TYPE == PGM_TYPE_NESTED
+    return 0;
+#else
     unsigned    cErrors = 0;
 
@@ -3768,4 +3785,6 @@
 #endif
     return cErrors;
+
+#endif /* PGM_SHW_TYPE != PGM_TYPE_NESTED */
 }
 #endif /* VBOX_STRICT */
Index: trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 9008)
+++ trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 9021)
@@ -255,5 +255,5 @@
     /* Note: CR8 reads will refer to V_TPR, so no need to catch them. */
     /** @note CR0 & CR4 can be safely read when guest and shadow copies are identical. */
-    if (!pVM->hwaccm.s.svm.fNestedPaging)
+    if (!pVM->hwaccm.s.fNestedPaging)
         pVMCB->ctrl.u16InterceptRdCRx = RT_BIT(0) | RT_BIT(3) | RT_BIT(4);
     else    
@@ -263,5 +263,5 @@
      * CR0/3/4 writes must be intercepted for obvious reasons.
      */
-    if (!pVM->hwaccm.s.svm.fNestedPaging)
+    if (!pVM->hwaccm.s.fNestedPaging)
         pVMCB->ctrl.u16InterceptWrCRx = RT_BIT(0) | RT_BIT(3) | RT_BIT(4) | RT_BIT(8);
     else
@@ -277,5 +277,5 @@
 
     pVMCB->ctrl.u32InterceptException = HWACCM_SVM_TRAP_MASK;
-    if (pVM->hwaccm.s.svm.fNestedPaging)
+    if (pVM->hwaccm.s.fNestedPaging)
         pVMCB->ctrl.u32InterceptException &= ~RT_BIT(14);   /* no longer need to intercept #PF. */
 
@@ -298,5 +298,5 @@
                                     ;
     /* With nested paging we don't care about invlpg anymore. */
-    if (pVM->hwaccm.s.svm.fNestedPaging)
+    if (pVM->hwaccm.s.fNestedPaging)
         pVMCB->ctrl.u32InterceptCtrl1 &= ~SVM_CTRL1_INTERCEPT_INVLPG;
 
@@ -595,5 +595,5 @@
         /* Note: WP is not relevant in nested paging mode as we catch accesses on the (host) physical level. */
         /* Note: In nested paging mode the guest is allowed to run with paging disabled; the guest physical to host physical translation will remain active. */
-        if (!pVM->hwaccm.s.svm.fNestedPaging)
+        if (!pVM->hwaccm.s.fNestedPaging)
         {
             val |= X86_CR0_PG;          /* Paging is always enabled; even when the guest is running in real mode or PE without paging. */
@@ -608,5 +608,5 @@
     {
         /* Save our shadow CR3 register. */
-        if (pVM->hwaccm.s.svm.fNestedPaging)
+        if (pVM->hwaccm.s.fNestedPaging)
         {
             pVMCB->ctrl.u64NestedPagingCR3  = PGMGetHyperCR3(pVM);
@@ -620,5 +620,5 @@
     {
         val = pCtx->cr4;
-        if (!pVM->hwaccm.s.svm.fNestedPaging)
+        if (!pVM->hwaccm.s.fNestedPaging)
         {
             switch(pVM->hwaccm.s.enmShadowMode)
@@ -729,5 +729,5 @@
     STAM_PROFILE_ADV_START(&pVM->hwaccm.s.StatEntry, x);
 
-    Assert(!pVM->hwaccm.s.svm.fNestedPaging);
+    Assert(!pVM->hwaccm.s.fNestedPaging);
     AssertReturn(pCpu->fSVMConfigured, VERR_EM_INTERNAL_ERROR);
 
@@ -814,5 +814,5 @@
 
     /* Enable nested paging if necessary (disabled each time after #VMEXIT). */
-    pVMCB->ctrl.NestedPaging.n.u1NestedPaging = pVM->hwaccm.s.svm.fNestedPaging;
+    pVMCB->ctrl.NestedPaging.n.u1NestedPaging = pVM->hwaccm.s.fNestedPaging;
 
     /* Force a TLB flush for the first world switch if the current cpu differs from the one we ran on last. */
@@ -1039,5 +1039,5 @@
     /* Note: no reason to sync back the CRx and DRx registers. They can't be changed by the guest. */
     /* Note: only in the nested paging case can CR3 & CR4 be changed by the guest. */ 
-    if (pVM->hwaccm.s.svm.fNestedPaging)
+    if (pVM->hwaccm.s.fNestedPaging)
     {
         CPUMSetGuestCR3(pVM, pVMCB->guest.u64CR3);
@@ -1145,5 +1145,5 @@
             RTGCUINTPTR uFaultAddress  = pVMCB->ctrl.u64ExitInfo2;     /* EXITINFO2 = fault address */
 
-            Assert(!pVM->hwaccm.s.svm.fNestedPaging);
+            Assert(!pVM->hwaccm.s.fNestedPaging);
 
             Log2(("Page fault at %VGv cr2=%VGv error code %x\n", pCtx->eip, uFaultAddress, errCode));
@@ -1283,5 +1283,5 @@
         RTGCPHYS    uFaultAddress  = pVMCB->ctrl.u64ExitInfo2;     /* EXITINFO2 = fault address */
 
-        Assert(pVM->hwaccm.s.svm.fNestedPaging);
+        Assert(pVM->hwaccm.s.fNestedPaging);
 
         Log2(("Page fault at %VGp cr2=%VGv error code %x\n", pCtx->eip, uFaultAddress, errCode));
@@ -1379,5 +1379,5 @@
         STAM_COUNTER_INC(&pVM->hwaccm.s.StatExitInvpg);
 
-        Assert(!pVM->hwaccm.s.svm.fNestedPaging);
+        Assert(!pVM->hwaccm.s.fNestedPaging);
 
         /* Truly a pita. Why can't SVM give the same information as VMX? */
@@ -1410,9 +1410,9 @@
             break;
         case 3:
-            Assert(!pVM->hwaccm.s.svm.fNestedPaging);
+            Assert(!pVM->hwaccm.s.fNestedPaging);
             pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_CR3;
             break;
         case 4:
-            Assert(!pVM->hwaccm.s.svm.fNestedPaging);
+            Assert(!pVM->hwaccm.s.fNestedPaging);
             pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_CR4;
             break;
