hv: fix tsc_deadline correctness issue

Fix tsc_deadline issue by trapping TSC_DEADLINE msr write if VMX_TSC_OFFSET is not 0.
Because there is an assupmtion in the ACRN vART design that pTSC_Adjust and vTSC_Adjust are
both 0.
We can leave the TSC_DEADLINE write pass-through without correctness issue becuase there is
no offset between the pTSC and vTSC, and there is no write to vTSC or vTSC_Adjust write observed
in the RTOS so far.
This commit fix the potential correctness issue, but the RT performance will be badly affected
if vTSC or vTSC_Adjust was not zero, which we will address if such case happened.

Tracked-On: #3636
Signed-off-by: Yan, Like <like.yan@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yan, Like 2019-08-29 16:53:09 +08:00 committed by ACRN System Integration
parent 3f84acda09
commit f15a3600ec
2 changed files with 32 additions and 3 deletions

View File

@ -427,7 +427,9 @@ static void vlapic_icrtmr_write_handler(struct acrn_vlapic *vlapic)
uint64_t vlapic_get_tsc_deadline_msr(const struct acrn_vlapic *vlapic)
{
uint64_t ret;
if (!vlapic_lvtt_tsc_deadline(vlapic)) {
if (is_lapic_pt_enabled(vlapic->vcpu)) {
ret = msr_read(MSR_IA32_TSC_DEADLINE) + exec_vmread64(VMX_TSC_OFFSET_FULL);
} else if (!vlapic_lvtt_tsc_deadline(vlapic)) {
ret = 0UL;
} else {
ret = (vlapic->vtimer.timer.fire_tsc == 0UL) ? 0UL :
@ -443,7 +445,11 @@ void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg)
struct hv_timer *timer;
uint64_t val = val_arg;
if (vlapic_lvtt_tsc_deadline(vlapic)) {
if (is_lapic_pt_enabled(vlapic->vcpu)) {
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, val);
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
msr_write(MSR_IA32_TSC_DEADLINE, val);
} else if (vlapic_lvtt_tsc_deadline(vlapic)) {
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, val);
timer = &vlapic->vtimer.timer;
@ -461,6 +467,8 @@ void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg)
} else {
timer->fire_tsc = 0UL;
}
} else {
/* No action required */
}
}

View File

@ -485,6 +485,23 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
return err;
}
/*
* If VMX_TSC_OFFSET_FULL is 0, no need to trap the write of IA32_TSC_DEADLINE because there is
* no offset between vTSC and pTSC, in this case, only write to vTSC_ADJUST is trapped.
*/
static void set_tsc_msr_intercept(struct acrn_vcpu *vcpu, bool intercept)
{
uint8_t *msr_bitmap = vcpu->arch.msr_bitmap;
if (!intercept) {
enable_msr_interception(msr_bitmap, MSR_IA32_TSC_DEADLINE, INTERCEPT_DISABLE);
enable_msr_interception(msr_bitmap, MSR_IA32_TSC_ADJUST, INTERCEPT_WRITE);
} else {
enable_msr_interception(msr_bitmap, MSR_IA32_TSC_DEADLINE, INTERCEPT_READ_WRITE);
enable_msr_interception(msr_bitmap, MSR_IA32_TSC_ADJUST, INTERCEPT_READ_WRITE);
}
}
/*
* Intel SDM 17.17.3: If an execution of WRMSR to the
* IA32_TIME_STAMP_COUNTER MSR adds (or subtracts) value X from the
@ -514,6 +531,8 @@ static void set_guest_tsc(struct acrn_vcpu *vcpu, uint64_t guest_tsc)
/* write to VMCS because rdtsc and rdtscp are not intercepted */
exec_vmwrite64(VMX_TSC_OFFSET_FULL, tsc_delta);
set_tsc_msr_intercept(vcpu, tsc_delta != 0UL);
}
/*
@ -561,6 +580,8 @@ static void set_guest_tsc_adjust(struct acrn_vcpu *vcpu, uint64_t tsc_adjust)
/* IA32_TSC_ADJUST is supposed to carry the value it's written to */
vcpu_set_guest_msr(vcpu, MSR_IA32_TSC_ADJUST, tsc_adjust);
set_tsc_msr_intercept(vcpu, (tsc_offset + tsc_adjust_delta ) != 0UL);
}
/**
@ -788,5 +809,5 @@ void update_msr_bitmap_x2apic_passthru(struct acrn_vcpu *vcpu)
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_XAPICID, INTERCEPT_READ);
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);
set_tsc_msr_intercept(vcpu, exec_vmread64(VMX_TSC_OFFSET_FULL) != 0UL);
}