hv: fix virtual TSC_DEADLINE msr read/write issues
When write to virtual TSC_DEADLINE, if virtual TSC_ADJUST is not zero: - when guest intends to disarm the tsc_deadline timer, should not arm the timer falsely; - when guest intends to arm the tsc_deadline timer, should not disarm the timer falsely. When read from virtual TSC_DEADLINE, if virtual TSC_ADJUST is not zero: - if physical TSC_DEADLINE is not zero, return the virtual TSC_DEADLINE value; - if physical TSC_DEADLINE is zero which means it's not armed (automatically disarmed after timer triggered), return 0 and reset the virtual TSC_DEADLINE. Tracked-On: #4162 Signed-off-by: Yan, Like <like.yan@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
e61412981d
commit
97916364fc
|
@ -427,8 +427,18 @@ static void vlapic_icrtmr_write_handler(struct acrn_vlapic *vlapic)
|
||||||
uint64_t vlapic_get_tsc_deadline_msr(const struct acrn_vlapic *vlapic)
|
uint64_t vlapic_get_tsc_deadline_msr(const struct acrn_vlapic *vlapic)
|
||||||
{
|
{
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
|
|
||||||
if (is_lapic_pt_enabled(vlapic->vcpu)) {
|
if (is_lapic_pt_enabled(vlapic->vcpu)) {
|
||||||
ret = msr_read(MSR_IA32_TSC_DEADLINE) + exec_vmread64(VMX_TSC_OFFSET_FULL);
|
/* If physical TSC_DEADLINE is zero which means it's not armed (automatically disarmed
|
||||||
|
* after timer triggered), return 0 and reset the virtual TSC_DEADLINE;
|
||||||
|
* If physical TSC_DEADLINE is not zero, return the virtual TSC_DEADLINE value.
|
||||||
|
*/
|
||||||
|
if (msr_read(MSR_IA32_TSC_DEADLINE) == 0UL) {
|
||||||
|
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, 0UL);
|
||||||
|
ret = 0UL;
|
||||||
|
} else {
|
||||||
|
ret = vcpu_get_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE);
|
||||||
|
}
|
||||||
} else if (!vlapic_lvtt_tsc_deadline(vlapic)) {
|
} else if (!vlapic_lvtt_tsc_deadline(vlapic)) {
|
||||||
ret = 0UL;
|
ret = 0UL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -437,7 +447,6 @@ uint64_t vlapic_get_tsc_deadline_msr(const struct acrn_vlapic *vlapic)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg)
|
void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg)
|
||||||
|
@ -447,8 +456,21 @@ void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg)
|
||||||
|
|
||||||
if (is_lapic_pt_enabled(vlapic->vcpu)) {
|
if (is_lapic_pt_enabled(vlapic->vcpu)) {
|
||||||
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, val);
|
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, val);
|
||||||
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
|
/* If val is not zero, which mean guest intends to arm the tsc_deadline timer,
|
||||||
msr_write(MSR_IA32_TSC_DEADLINE, val);
|
* if the calculated value to write to the physical TSC_DEADLINE msr is zero,
|
||||||
|
* we plus 1 to not disarm the physcial timer falsely;
|
||||||
|
* If val is zero, which means guest intends to disarm the tsc_deadline timer,
|
||||||
|
* we disarm the physical timer.
|
||||||
|
*/
|
||||||
|
if (val != 0UL) {
|
||||||
|
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
|
||||||
|
if (val == 0UL) {
|
||||||
|
val += 1UL;
|
||||||
|
}
|
||||||
|
msr_write(MSR_IA32_TSC_DEADLINE, val);
|
||||||
|
} else {
|
||||||
|
msr_write(MSR_IA32_TSC_DEADLINE, 0);
|
||||||
|
}
|
||||||
} else if (vlapic_lvtt_tsc_deadline(vlapic)) {
|
} else if (vlapic_lvtt_tsc_deadline(vlapic)) {
|
||||||
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, val);
|
vcpu_set_guest_msr(vlapic->vcpu, MSR_IA32_TSC_DEADLINE, val);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue