HRESULT WhSeMapHostToGuestVirtualMemory(whpx_state
*
Partition, uintptr_t HostVa,
uintptr_t
*
GuestVa, size_t Size,
WHSE_MEMORY_ACCESS_FLAGS Flags)
{
auto size
=
ALIGN_UP(Size);
PWHSE_ALLOCATION_NODE existingNode
=
nullptr;
auto hresult
=
WhSeFindAllocationNodeByGva(Partition,
*
GuestVa, &existingNode);
uintptr_t suggestedGva
=
0
;
if
(
*
GuestVa
=
=
0
|| existingNode !
=
nullptr) {
auto hresult
=
WhSiSuggestVirtualAddress(
Partition, size, &suggestedGva, Partition
-
>VirtualProcessor.Mode);
}
else
suggestedGva
=
ALIGN(
*
GuestVa);
existingNode
=
nullptr;
hresult
=
WhSeFindAllocationNodeByGva(Partition, suggestedGva, &existingNode);
auto startingGva
=
ALIGN(suggestedGva);
auto endingGva
=
ALIGN_UP(startingGva
+
size);
uintptr_t suggestedGpa
=
0
;
hresult
=
WhSiSuggestPhysicalAddress(Partition, size, &suggestedGpa);
WHSE_ALLOCATION_NODE node{.BlockType
=
MEMORY_BLOCK_TYPE::MemoryBlockVirtual,
.HostVirtualAddress
=
HostVa,
.GuestPhysicalAddress
=
suggestedGpa,
.GuestVirtualAddress
=
startingGva,
.Size
=
size};
hresult
=
WhSeInsertAllocationTrackingNode(Partition, node);
/
/
Setup matching PTEs
for
(auto gva
=
startingGva, page
=
suggestedGpa; gva < endingGva;
gva
+
=
PAGE_SIZE, page
+
=
PAGE_SIZE) {
hresult
=
WhSiInsertPageTableEntry(Partition, gva, page);
hresult
=
::WHvMapGpaRange(
Partition
-
>partition, reinterpret_cast<PVOID>(HostVa),
static_cast<WHV_GUEST_PHYSICAL_ADDRESS>(suggestedGpa), size, Flags);
*
GuestVa
=
startingGva;
return
hresult;
}
HRESULT WhSiInsertPageTableEntry(whpx_state
*
Partition,
uintptr_t VirtualAddress,
uintptr_t PhysicalAddress)
{
/
/
"Explode"
the VA into translation indexes
uint16_t pml4Idx;
uint16_t pdpIdx;
uint16_t pdIdx;
uint16_t ptIdx;
uint16_t phyOffset;
auto hresult
=
WhSiDecomposeVirtualAddress(
VirtualAddress, &pml4Idx, &pdpIdx, &pdIdx, &ptIdx, &phyOffset);
/
/
Search entry
in
PML4
auto pml4e
=
reinterpret_cast<PMMPTE_HARDWARE>(
Partition
-
>MemoryLayout.Pml4HostVa)[pml4Idx];
if
(pml4e.Valid
=
=
FALSE) {
/
/
Shouldn't happen as we initialized
all
PLM4 entries upfront
return
HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR);
}
/
/
Search entry
in
Page Directory Pointers
uintptr_t pdpHva
=
0
;
hresult
=
WhSpLookupHVAFromPFN(Partition, pml4e.PageFrameNumber, &pdpHva);
auto pdp
=
reinterpret_cast<PMMPTE_HARDWARE>(pdpHva);
auto pdpe
=
pdp[pdpIdx];
if
(pdpe.Valid
=
=
FALSE) {
/
/
Allocate a Page Directory page
/
/
hresult
=
WhSpInsertPageTableEntry(Partition, pdp, pdpIdx);
pdpe
=
pdp[pdpIdx];
}
/
/
Search entry
in
Page Directories
uintptr_t pdHva
=
0
;
hresult
=
WhSpLookupHVAFromPFN(Partition, pdpe.PageFrameNumber, &pdHva);
if
(FAILED(hresult))
return
hresult;
auto pd
=
reinterpret_cast<PMMPTE_HARDWARE>(pdHva);
auto pde
=
pd[pdIdx];
if
(pde.Valid
=
=
FALSE) {
/
/
Allocate a Page Table page
hresult
=
WhSpInsertPageTableEntry(Partition, pd, pdIdx);
pde
=
pd[pdIdx];
}
/
/
Add entry
in
Page Tables
uintptr_t ptHva
=
0
;
hresult
=
WhSpLookupHVAFromPFN(Partition, pde.PageFrameNumber, &ptHva);
if
(FAILED(hresult))
return
hresult;
auto pt
=
reinterpret_cast<PMMPTE_HARDWARE>(ptHva);
auto ppte
=
&pt[ptIdx];
if
(ppte
-
>Valid
=
=
FALSE) {
/
*
PWHSE_ALLOCATION_NODE found
=
nullptr;
hresult
=
WhSeFindAllocationNodeByGpa( Partition, PhysicalAddress,
&found );
if
( hresult !
=
HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) &&
FAILED( hresult ) )
return
hresult;
/
/
Create a valid PTE
MMPTE_HARDWARE pte{};
pte.AsUlonglong
=
0
;
/
/
Ensure zeroed
pte.Valid
=
1
;
/
/
Intel's Present bit
pte.Write
=
1
;
/
/
Intel's Read
/
Write bit
pte.Owner
=
1
;
/
/
Intel
's User/Supervisor bit, let'
s say it
is
a user
/
/
accessible frame
pte.PageFrameNumber
=
(PhysicalAddress
/
PAGE_SIZE);
/
/
Physical address of PDP page
*
ppte
=
pte;
WHSE_ALLOCATION_NODE node{.BlockType
=
MEMORY_BLOCK_TYPE::MemoryBlockPte,
.HostVirtualAddress
=
0
,
.GuestPhysicalAddress
=
PhysicalAddress,
.GuestVirtualAddress
=
0
,
.Size
=
PAGE_SIZE};
hresult
=
WhSeInsertAllocationTrackingNode(Partition, node);
}
return
S_OK;
}