VirtualBox

Ignore:
Timestamp:
Oct 9, 2019 8:04:51 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133846
Message:

EFI/Firmware: Should always use atomics when updating 64-bit page table entries (see PGMSHWPTEPAE_ATOMIC_SET and such). Cache the old page table entry value instead of reading it 512 times when converting the tables. Do similar stuff for ConvertPageEntryAttribute and make it skip writing the same value back. bugref:4643

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuPageTable.c

    r81193 r81195  
    1818#include <Register/Intel/Cpuid.h>
    1919#include <Register/Intel/Msr.h>
     20#ifdef VBOX
     21# define IN_RING0
     22# include <iprt/asm.h>
     23#endif
    2024
    2125#include "CpuDxe.h"
     
    97101UINT64                    *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];
    98102
     103#ifdef VBOX
     104/**
     105 Safe page table entry write function, make 104% sure the compiler won't
     106 split up the access (fatal if modifying entries for current code or data).
     107
     108 @param[in] PageEntry        The page table entry to modify.*
     109 @param[in] CurrentPageEntry The old page table value (for cmpxchg8b).
     110 @param[in] NewPageEntry     What to write.
     111**/
     112static VOID SafePageTableEntryWrite64 (UINT64 volatile *PageEntry, UINT64 CurrentPageEntry, UINT64 NewPageEntry)
     113{
     114# ifdef VBOX
     115  ASMAtomicWriteU64(PageEntry, NewPageEntry); RT_NOREF(CurrentPageEntry);
     116# else
     117  for (;;) {
     118    UINT64 CurValue = InterlockedCompareExchange64(PageEntry, CurrentPageEntry, NewPageEntry);
     119    if (CurValue == CurrentPageEntry)
     120      return;
     121    CurrentPageEntry = CurValue;
     122  }
     123# endif
     124}
     125#endif
     126
    99127/**
    100128 Check if current execution environment is in SMM mode or not, via
     
    388416ConvertPageEntryAttribute (
    389417  IN  PAGE_TABLE_LIB_PAGING_CONTEXT     *PagingContext,
     418#ifdef VBOX
     419  IN  UINT64 volatile                   *PageEntry,
     420#else
    390421  IN  UINT64                            *PageEntry,
     422#endif
    391423  IN  UINT64                            Attributes,
    392424  IN  PAGE_ACTION                       PageAction,
     
    461493    }
    462494  }
     495#ifndef VBOX
    463496  *PageEntry = NewPageEntry;
     497#endif
    464498  if (CurrentPageEntry != NewPageEntry) {
     499#ifdef VBOX
     500    SafePageTableEntryWrite64 (PageEntry, CurrentPageEntry, NewPageEntry);
     501#endif
    465502    *IsModified = TRUE;
    466503    DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry));
     
    519556SplitPage (
    520557#ifdef VBOX
    521   IN  volatile UINT64                   *PageEntry,
     558  IN  UINT64 volatile                   *PageEntry,
    522559#else
    523560  IN  UINT64                            *PageEntry,
     
    529566{
    530567  UINT64   BaseAddress;
     568#ifdef VBOX
     569  UINT64   CurrentPageEntry;
     570#endif
    531571  UINT64   *NewPageEntry;
    532572  UINTN    Index;
     
    552592        return RETURN_OUT_OF_RESOURCES;
    553593      }
     594#ifdef VBOX
     595      CurrentPageEntry = *PageEntry;
     596      BaseAddress = CurrentPageEntry & ~AddressEncMask & PAGING_2M_ADDRESS_MASK_64;
     597#else
    554598      BaseAddress = *PageEntry & ~AddressEncMask & PAGING_2M_ADDRESS_MASK_64;
     599#endif
    555600      for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {
     601#ifdef VBOX
     602        NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | AddressEncMask | (CurrentPageEntry & PAGE_PROGATE_BITS);
     603#else
    556604        NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | AddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS);
    557       }
     605#endif
     606      }
     607#ifdef VBOX
     608      SafePageTableEntryWrite64 (PageEntry, CurrentPageEntry,
     609                                 (UINT64)(UINTN)NewPageEntry | AddressEncMask | (CurrentPageEntry & PAGE_ATTRIBUTE_BITS));
     610#else
    558611      (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | ((*PageEntry) & PAGE_ATTRIBUTE_BITS);
     612#endif
    559613      return RETURN_SUCCESS;
    560614    } else {
     
    573627        return RETURN_OUT_OF_RESOURCES;
    574628      }
     629#ifdef VBOX
     630      CurrentPageEntry = *PageEntry;
     631      BaseAddress = CurrentPageEntry & ~AddressEncMask  & PAGING_1G_ADDRESS_MASK_64;
     632#else
    575633      BaseAddress = *PageEntry & ~AddressEncMask  & PAGING_1G_ADDRESS_MASK_64;
     634#endif
    576635      for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {
     636#ifdef VBOX
     637        NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | AddressEncMask | IA32_PG_PS | (CurrentPageEntry & PAGE_PROGATE_BITS);
     638#else
    577639        NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | AddressEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS);
    578       }
     640#endif
     641      }
     642#ifdef VBOX
     643      SafePageTableEntryWrite64 (PageEntry, CurrentPageEntry,
     644                                 (UINT64)(UINTN)NewPageEntry | AddressEncMask | (CurrentPageEntry & PAGE_ATTRIBUTE_BITS));
     645#else
    579646      (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | ((*PageEntry) & PAGE_ATTRIBUTE_BITS);
     647#endif
    580648      return RETURN_SUCCESS;
    581649    } else {
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette