mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-21 01:24:19 +00:00
hv: nested: fix bug in syncing EPTP from VMCS12 to VMCS02
Currently vmptrld_vmexit_handler() doesn't sync VMX_EPT_POINTER_FULL from vmcs12 to vmcs02, instead it sets gpa_field_dirty and relies on nested_vmentry() to sync EPTP in next nested VMentry. This creates readability issue since all other intercepted VMCS fields are synced in sync_vmcs12_to_vmcs02(). Another issue is that other VMCS fields managed by gpa_field_dirty are repeatedly synced in both vmptrld and nested vmentry handler. This patch moves get_nept_desc() ahead of sync_vmcs12_to_vmcs02(), such that shadow_eptp is allocated before sync_vmcs12_to_vmcs02() which can sync EPTP properly. BTW, in nested_vmexit_handler(), don't need to read from VMCS to get the exit reason, since vcpu->arch.exit_reason has it already. Tracked-On: #5923 Signed-off-by: Zide Chen <zide.chen@intel.com>
This commit is contained in:
parent
01bf5110c5
commit
6376d5a0d3
@ -972,6 +972,9 @@ static void sync_vmcs12_to_vmcs02(struct acrn_vcpu *vcpu)
|
|||||||
val64 = vmcs12_read_field(vmcs12, VMX_MSR_BITMAP_FULL);
|
val64 = vmcs12_read_field(vmcs12, VMX_MSR_BITMAP_FULL);
|
||||||
exec_vmwrite(VMX_MSR_BITMAP_FULL, gpa2hpa(vcpu->vm, val64));
|
exec_vmwrite(VMX_MSR_BITMAP_FULL, gpa2hpa(vcpu->vm, val64));
|
||||||
|
|
||||||
|
val64 = vmcs12_read_field(vmcs12, VMX_EPT_POINTER_FULL);
|
||||||
|
exec_vmwrite(VMX_EPT_POINTER_FULL, get_shadow_eptp(val64));
|
||||||
|
|
||||||
/* For VM-execution, entry and exit controls */
|
/* For VM-execution, entry and exit controls */
|
||||||
adjust_vmcs02_control_fields(vcpu);
|
adjust_vmcs02_control_fields(vcpu);
|
||||||
}
|
}
|
||||||
@ -1140,11 +1143,12 @@ int32_t vmptrld_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||||||
/* Load VMCS12 from L1 guest memory */
|
/* Load VMCS12 from L1 guest memory */
|
||||||
(void)copy_from_gpa(vcpu->vm, (void *)&nested->vmcs12, vmcs12_gpa,
|
(void)copy_from_gpa(vcpu->vm, (void *)&nested->vmcs12, vmcs12_gpa,
|
||||||
sizeof(struct acrn_vmcs12));
|
sizeof(struct acrn_vmcs12));
|
||||||
vcpu->arch.nested.gpa_field_dirty = true;
|
|
||||||
|
/* if needed, create nept_desc and allocate shadow root for the EPTP */
|
||||||
|
get_nept_desc(nested->vmcs12.ept_pointer);
|
||||||
|
|
||||||
/* Need to load shadow fields from this new VMCS12 to VMCS02 */
|
/* Need to load shadow fields from this new VMCS12 to VMCS02 */
|
||||||
sync_vmcs12_to_vmcs02(vcpu);
|
sync_vmcs12_to_vmcs02(vcpu);
|
||||||
get_nept_desc(nested->vmcs12.ept_pointer);
|
|
||||||
|
|
||||||
/* Before VMCS02 is being used as a shadow VMCS, VMCLEAR it */
|
/* Before VMCS02 is being used as a shadow VMCS, VMCLEAR it */
|
||||||
clear_va_vmcs(nested->vmcs02);
|
clear_va_vmcs(nested->vmcs02);
|
||||||
@ -1343,7 +1347,7 @@ int32_t nested_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||||||
struct acrn_vmcs12 *vmcs12 = (struct acrn_vmcs12 *)&vcpu->arch.nested.vmcs12;
|
struct acrn_vmcs12 *vmcs12 = (struct acrn_vmcs12 *)&vcpu->arch.nested.vmcs12;
|
||||||
bool is_l1_vmexit = true;
|
bool is_l1_vmexit = true;
|
||||||
|
|
||||||
if ((exec_vmread(VMX_EXIT_REASON) & 0xFFFFU) == VMX_EXIT_REASON_EPT_VIOLATION) {
|
if ((vcpu->arch.exit_reason & 0xFFFFU) == VMX_EXIT_REASON_EPT_VIOLATION) {
|
||||||
is_l1_vmexit = handle_l2_ept_violation(vcpu);
|
is_l1_vmexit = handle_l2_ept_violation(vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user