Skip to content
This repository was archived by the owner on Jan 28, 2023. It is now read-only.

Commit 9060aa0

Browse files
committed
Avoid flushing outdated PDPTE0..3 cache to VMCS
Signed-off-by: Alexey Romko <nevilad@yahoo.com>
1 parent 6dcbc7a commit 9060aa0

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

core/include/vcpu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ struct vcpu_t {
200200
uint64_t fs_base_dirty : 1;
201201
uint64_t interruptibility_dirty : 1;
202202
uint64_t pcpu_ctls_dirty : 1;
203-
uint64_t padding : 46;
203+
uint64_t pae_pdpt_dirty : 1;
204+
uint64_t padding : 45;
204205
};
205206

206207
/* For TSC offseting feature*/

core/vcpu.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,7 @@ static int vcpu_prepare_pae_pdpt(struct vcpu_t *vcpu)
18591859
cr3, ret);
18601860
return ret < 0 ? ret : -EIO;
18611861
}
1862+
vcpu->pae_pdpt_dirty = 1;
18621863
return 0;
18631864
#else // !CONFIG_HAX_EPT2
18641865
uint64_t gpfn = (cr3 & 0xfffff000) >> PG_ORDER_4K;
@@ -1880,6 +1881,7 @@ static int vcpu_prepare_pae_pdpt(struct vcpu_t *vcpu)
18801881
#else // !HAX_ARCH_X86_64, i.e. HAX_ARCH_X86_32
18811882
hax_unmap_gpfn(vcpu->vm, buf, gpfn);
18821883
#endif // HAX_ARCH_X86_64
1884+
vcpu->pae_pdpt_dirty = 1;
18831885
return 0;
18841886
#endif // CONFIG_HAX_EPT2
18851887
}
@@ -1966,16 +1968,21 @@ static void vmwrite_cr(struct vcpu_t *vcpu)
19661968
// eptp);
19671969
vmwrite(vcpu, GUEST_CR3, state->_cr3);
19681970
scpu_ctls |= ENABLE_EPT;
1969-
// Set PDPTEs for vCPU if it's in or about to enter PAE paging mode
1970-
if ((state->_cr4 & CR4_PAE) && !(state->_efer & IA32_EFER_LME) &&
1971-
(state->_cr0 & CR0_PG)) {
1972-
// vcpu_prepare_pae_pdpt() has populated vcpu->pae_pdptes
1973-
// TODO: Enable CR3_LOAD_EXITING so as to update vcpu->pae_pdptes
1974-
// whenever guest writes to CR3 in EPT+PAE mode
1971+
if (vcpu->pae_pdpt_dirty) {
1972+
// vcpu_prepare_pae_pdpt() has updated vcpu->pae_pdptes
1973+
// Note that because we do not monitor guest writes to CR3, the only
1974+
// case where vcpu->pae_pdptes is newer than VMCS GUEST_PDPTE{0..3}
1975+
// is following a guest write to CR0 or CR4 that requires PDPTEs to
1976+
// be reloaded, i.e. the pae_pdpt_dirty case. When the guest is in
1977+
// PAE paging mode but !pae_pdpt_dirty, VMCS GUEST_PDPTE{0..3} are
1978+
// already up-to-date following each VM exit (see Intel SDM Vol. 3C
1979+
// 27.3.4), and we must not overwrite them with our cached values
1980+
// (vcpu->pae_pdptes), which may be outdated.
19751981
vmwrite(vcpu, GUEST_PDPTE0, vcpu->pae_pdptes[0]);
19761982
vmwrite(vcpu, GUEST_PDPTE1, vcpu->pae_pdptes[1]);
19771983
vmwrite(vcpu, GUEST_PDPTE2, vcpu->pae_pdptes[2]);
19781984
vmwrite(vcpu, GUEST_PDPTE3, vcpu->pae_pdptes[3]);
1985+
vcpu->pae_pdpt_dirty = 0;
19791986
}
19801987
vmwrite(vcpu, VMX_EPTP, eptp);
19811988
// pcpu_ctls |= RDTSC_EXITING;

0 commit comments

Comments
 (0)