From 7b976e63a3d80c83d3944fb9dea815ad7c042195 Mon Sep 17 00:00:00 2001 From: Petr Benes Date: Sun, 5 Jan 2020 17:05:36 +0100 Subject: [PATCH] introduce ept_t::map_identity_sparse() method --- src/hvpp/hvpp/ept.cpp | 41 +++++++++++++++++++++++++++++++++++------ src/hvpp/hvpp/ept.h | 1 + src/hvpp/hvpp/hvpp.cpp | 19 +++++++++++++++++++ src/hvpp/hvpp/hvpp.h | 13 +++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/hvpp/hvpp/ept.cpp b/src/hvpp/hvpp/ept.cpp index c017e44..19511c3 100644 --- a/src/hvpp/hvpp/ept.cpp +++ b/src/hvpp/hvpp/ept.cpp @@ -71,12 +71,6 @@ void ept_t::map_identity(epte_t::access_type access /* = epte_t::access_type::re // loss. // - // - // TODO: - // - Map only valid physical memory ranges? - // - Map up to max valid physical memory address? (incl. "holes") - // - static constexpr auto _512gb = 512ull * 1024 * 1024 * 1024; @@ -87,6 +81,41 @@ void ept_t::map_identity(epte_t::access_type access /* = epte_t::access_type::re } } +void ept_t::map_identity_sparse(epte_t::access_type access /* = epte_t::access_type::read_write_execute */) noexcept +{ + // + // This method is similar to the map_identity() method above, except that + // the memory is covered by using physical_memory_descriptor() as opposed to + // covering the first 512 GB of physical memory. + // + // The benefit of this approach is that it uses significantly less memory + // for the EPT structures. Only addresses backed by actual physical memory + // are mapped (considering that the machine doesn't have 512 GB+). + // + // The drawback of this approach is that it doesn't cover MMIO address ranges. + // Therefore there is a good chance that you'll receive several EPT violations. + // EPT violation handler then should create and map EPT entries for the missing + // pages. + // + + // + // #TODO + // Consider combined approach where the first 4GB is mapped unconditionally (most + // MMIO is there) and rest is filled with physical_memory_descriptor(). + // + + for (auto& range : mm::physical_memory_descriptor()) + { + auto from = pa_t{ page_align (range.begin().value(), pd_t{}) }; + auto to = pa_t{ page_align_up(range.end().value(), pd_t{}) }; + + for (pa_t pa = from; pa < to; pa += ept_pd_t::size) + { + map_2mb(pa, pa, access); + } + } +} + epte_t* ept_t::map(pa_t guest_pa, pa_t host_pa, epte_t::access_type access /* = epte_t::access_type::read_write_execute */, pml level /* = pml::pt */) noexcept diff --git a/src/hvpp/hvpp/ept.h b/src/hvpp/hvpp/ept.h index b661b93..c0ab660 100644 --- a/src/hvpp/hvpp/ept.h +++ b/src/hvpp/hvpp/ept.h @@ -20,6 +20,7 @@ class ept_t final ept_t& operator=(ept_t&& other) noexcept = delete; void map_identity(epte_t::access_type access = epte_t::access_type::read_write_execute) noexcept; + void map_identity_sparse(epte_t::access_type access = epte_t::access_type::read_write_execute) noexcept; epte_t* map (pa_t guest_pa, pa_t host_pa, epte_t::access_type access = epte_t::access_type::read_write_execute, diff --git a/src/hvpp/hvpp/hvpp.cpp b/src/hvpp/hvpp/hvpp.cpp index f8b66fd..7e0177a 100644 --- a/src/hvpp/hvpp/hvpp.cpp +++ b/src/hvpp/hvpp/hvpp.cpp @@ -90,6 +90,25 @@ HvppEptMapIdentityEx( ept_->map_identity((epte_t::access_type)(Access)); } +VOID +NTAPI +HvppEptMapIdentitySparse( + _In_ PEPT Ept + ) +{ + ept_->map_identity_sparse(); +} + +VOID +NTAPI +HvppEptMapIdentitySparseEx( + _In_ PEPT Ept, + _In_ ULONG Access + ) +{ + ept_->map_identity_sparse((epte_t::access_type)(Access)); +} + PEPTE NTAPI HvppEptMap( diff --git a/src/hvpp/hvpp/hvpp.h b/src/hvpp/hvpp/hvpp.h index 01ad351..823c0e5 100644 --- a/src/hvpp/hvpp/hvpp.h +++ b/src/hvpp/hvpp/hvpp.h @@ -1197,6 +1197,19 @@ HvppEptMapIdentityEx( _In_ ULONG Access ); +VOID +NTAPI +HvppEptMapIdentitySparse( + _In_ PEPT Ept + ); + +VOID +NTAPI +HvppEptMapIdentitySparseEx( + _In_ PEPT Ept, + _In_ ULONG Access + ); + PEPTE NTAPI HvppEptMap(