diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index a665840bb..a4a7627b2 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -437,8 +437,11 @@ static void init_exec_ctrl(struct acrn_vcpu *vcpu) /* Set up executive VMCS pointer - pg 2905 24.6.10 */ exec_vmwrite64(VMX_EXECUTIVE_VMCS_PTR_FULL, 0UL); - /* Setup Time stamp counter offset - pg 2902 24.6.5 */ - exec_vmwrite64(VMX_TSC_OFFSET_FULL, 0UL); + /* Setup Time stamp counter offset - pg 2902 24.6.5 + * VMCS.OFFSET = vAdjust - pAdjust + */ + value64 = vcpu_get_guest_msr(vcpu, MSR_IA32_TSC_ADJUST) - cpu_msr_read(MSR_IA32_TSC_ADJUST); + exec_vmwrite64(VMX_TSC_OFFSET_FULL, value64); /* Set up the link pointer */ exec_vmwrite64(VMX_VMS_LINK_PTR_FULL, 0xFFFFFFFFFFFFFFFFUL); diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c index a639157d4..26acd7034 100644 --- a/hypervisor/arch/x86/guest/vmsr.c +++ b/hypervisor/arch/x86/guest/vmsr.c @@ -456,6 +456,10 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu) * IA32_TIME_STAMP_COUNTER MSR adds (or subtracts) value X from the * TSC, the logical processor also adds (or subtracts) value X from * the IA32_TSC_ADJUST MSR. + * + * So, here we should update VMCS.OFFSET and vAdjust accordingly. + * - VMCS.OFFSET = vTSC - pTSC + * - vAdjust += VMCS.OFFSET's delta */ /** @@ -478,10 +482,33 @@ static void set_guest_tsc(struct acrn_vcpu *vcpu, uint64_t guest_tsc) exec_vmwrite64(VMX_TSC_OFFSET_FULL, tsc_delta); } +/* + * The policy of vART is that software in native can run in VM too. And in native side, + * the relationship between the ART hardware and TSC is: + * + * pTSC = (pART * M) / N + pAdjust + * + * The vART solution is: + * - Present the ART capability to guest through CPUID leaf + * 15H for M/N which identical to the physical values. + * - PT devices see the pART (vART = pART). + * - Guest expect: vTSC = vART * M / N + vAdjust. + * - VMCS.OFFSET = vTSC - pTSC = vAdjust - pAdjust. + * + * So to support vART, we should do the following: + * 1. if vAdjust and vTSC are changed by guest, we should change + * VMCS.OFFSET accordingly. + * 2. Make the assumption that the pAjust is never touched by ACRN. + */ + /* * Intel SDM 17.17.3: "If an execution of WRMSR to the IA32_TSC_ADJUST * MSR adds (or subtracts) value X from that MSR, the logical * processor also adds (or subtracts) value X from the TSC." + * + * So, here we should update VMCS.OFFSET and vAdjust accordingly. + * - VMCS.OFFSET += vAdjust's delta + * - vAdjust = new vAdjust set by guest */ /** @@ -728,5 +755,4 @@ void update_msr_bitmap_x2apic_passthru(struct acrn_vcpu *vcpu) enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_LDR, INTERCEPT_READ); enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_ICR, INTERCEPT_WRITE); enable_msr_interception(msr_bitmap, MSR_IA32_TSC_DEADLINE, INTERCEPT_DISABLE); - enable_msr_interception(msr_bitmap, MSR_IA32_TSC_ADJUST, INTERCEPT_DISABLE); }