Index: /trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c
===================================================================
--- /trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c	(revision 81195)
+++ /trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c	(revision 81196)
@@ -13,4 +13,8 @@
 #include <Library/CpuLib.h>
 #include <Library/BaseLib.h>
+#ifdef VBOX
+# define IN_RING0
+# include <iprt/asm.h>
+#endif
 
 #include "CpuMpPei.h"
@@ -68,4 +72,28 @@
 };
 
+#ifdef VBOX
+/**
+ Safe page table entry write function, make 104% sure the compiler won't
+ split up the access (fatal if modifying entries for current code or data).
+
+ @param[in] PageEntry        The page table entry to modify.*
+ @param[in] CurrentPageEntry The old page table value (for cmpxchg8b).
+ @param[in] NewPageEntry     What to write.
+**/
+static VOID SafePageTableEntryWrite64 (UINT64 volatile *PageEntry, UINT64 CurrentPageEntry, UINT64 NewPageEntry)
+{
+# ifdef VBOX
+  ASMAtomicWriteU64(PageEntry, NewPageEntry); RT_NOREF(CurrentPageEntry);
+# else
+  for (;;) {
+    UINT64 CurValue = InterlockedCompareExchange64(PageEntry, CurrentPageEntry, NewPageEntry);
+    if (CurValue == CurrentPageEntry)
+      return;
+    CurrentPageEntry = CurValue;
+  }
+# endif
+}
+#endif
+
 /**
   The function will check if IA32 PAE is supported.
@@ -235,5 +263,9 @@
 RETURN_STATUS
 SplitPage (
+#ifdef VBOX
+  IN  UINT64 volatile                   *PageEntry,
+#else
   IN  UINT64                            *PageEntry,
+#endif
   IN  PAGE_ATTRIBUTE                    PageAttribute,
   IN  PAGE_ATTRIBUTE                    SplitAttribute,
@@ -241,4 +273,7 @@
   )
 {
+#ifdef VBOX
+  UINT64            CurrentPageEntry;
+#endif
   UINT64            BaseAddress;
   UINT64            *NewPageEntry;
@@ -265,10 +300,19 @@
   AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &
                    mPageAttributeTable[SplitTo].AddressMask;
+#ifdef VBOX
+  CurrentPageEntry = *PageEntry;
+  BaseAddress    = CurrentPageEntry &
+#else
   BaseAddress    = *PageEntry &
+#endif
                    ~PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &
                    mPageAttributeTable[PageAttribute].AddressMask;
   for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {
     NewPageEntry[Index] = BaseAddress | AddressEncMask |
+#ifdef VBOX
+                          (CurrentPageEntry & PAGE_PROGATE_BITS);
+#else
                           ((*PageEntry) & PAGE_PROGATE_BITS);
+#endif
 
     if (SplitTo != PageMin) {
@@ -283,5 +327,10 @@
   }
 
+#ifdef VBOX
+  SafePageTableEntryWrite64 (PageEntry, CurrentPageEntry,
+                             (UINT64)(UINTN)NewPageEntry | AddressEncMask | PAGE_ATTRIBUTE_BITS);
+#else
   (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | PAGE_ATTRIBUTE_BITS;
+#endif
 
   return RETURN_SUCCESS;
@@ -318,5 +367,10 @@
   )
 {
+#ifdef VBOX
+  UINT64 volatile                   *PageEntry;
+  UINT64                            CurrentPageEntry;
+#else
   UINT64                            *PageEntry;
+#endif
   PAGE_ATTRIBUTE                    PageAttribute;
   RETURN_STATUS                     Status;
@@ -364,4 +418,10 @@
     // Just take care of 'present' bit for Stack Guard.
     //
+#ifdef VBOX
+    CurrentPageEntry = *PageEntry;
+    if ((CurrentPageEntry & IA32_PG_P) != (Attributes & IA32_PG_P))
+      SafePageTableEntryWrite64 (PageEntry, CurrentPageEntry,
+                                 (CurrentPageEntry & ~(UINT64)IA32_PG_P) | (Attributes & IA32_PG_P));
+#else
     if ((Attributes & IA32_PG_P) != 0) {
       *PageEntry |= (UINT64)IA32_PG_P;
@@ -369,4 +429,5 @@
       *PageEntry &= ~((UINT64)IA32_PG_P);
     }
+#endif
 
     //
