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

Commit e39e298

Browse files
authored
Merge pull request #152 from nevilad/pae_issues
Fixed PAE issues
2 parents 6dcbc7a + ecd359f commit e39e298

3 files changed

Lines changed: 26 additions & 13 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/page_walker.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,8 @@ uint32_t pw_perform_page_walk(
616616
first_table = pw_retrieve_table_from_cr3(cr3, is_pae, is_lme);
617617

618618
if (is_pae) {
619+
uint8_t *pdpt_page_hva;
620+
619621
if (is_lme) {
620622
pml4t_gpa = first_table;
621623
#ifdef CONFIG_HAX_EPT2
@@ -655,21 +657,24 @@ uint32_t pw_perform_page_walk(
655657
}
656658

657659
#ifdef CONFIG_HAX_EPT2
658-
pdpt_hva = gpa_space_map_page(&vcpu->vm->gpa_space,
659-
pdpt_gpa >> PG_ORDER_4K,
660-
&pdpt_kmap, NULL);
660+
pdpt_page_hva = gpa_space_map_page(&vcpu->vm->gpa_space,
661+
pdpt_gpa >> PG_ORDER_4K,
662+
&pdpt_kmap, NULL);
661663
#else // !CONFIG_HAX_EPT2
662664
#ifdef HAX_ARCH_X86_32
663-
pdpt_hva = hax_map_gpfn(vcpu->vm, pdpt_gpa >> 12, is_kernel, cr3, 1);
665+
pdpt_page_hva = hax_map_gpfn(vcpu->vm, pdpt_gpa >> 12, is_kernel, cr3, 1);
664666
#else
665-
pdpt_hva = hax_map_gpfn(vcpu->vm, pdpt_gpa >> 12);
667+
pdpt_page_hva = hax_map_gpfn(vcpu->vm, pdpt_gpa >> 12);
666668
#endif
667669
#endif // CONFIG_HAX_EPT2
668-
if (pdpt_hva == NULL) {
670+
if (pdpt_page_hva == NULL) {
669671
retval = TF_FAILED;
670672
goto out;
671673
}
672674

675+
// In PAE paging mode, pdpt_gpa is 32-byte aligned, not 4KB-aligned
676+
pdpt_hva = pdpt_page_hva + (uint)(pdpt_gpa & (PAGE_SIZE_4K - 1));
677+
673678
pdpte_ptr = pw_retrieve_table_entry(vcpu, pdpt_hva, pdpte_index,
674679
is_pae);
675680
pw_read_entry_value(&pdpte_val, pdpte_ptr, is_pae);

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)