Skip to content

Commit adafea1

Browse files
yamahatabonzini
authored andcommitted
KVM: x86: Add infrastructure for secure TSC
Add guest_tsc_protected member to struct kvm_arch_vcpu and prohibit changing TSC offset/multiplier when guest_tsc_protected is true. X86 confidential computing technology defines protected guest TSC so that the VMM can't change the TSC offset/multiplier once vCPU is initialized. SEV-SNP defines Secure TSC as optional, whereas TDX mandates it. KVM has common logic on x86 that tries to guess or adjust TSC offset/multiplier for better guest TSC and TSC interrupt latency at KVM vCPU creation (kvm_arch_vcpu_postcreate()), vCPU migration over pCPU (kvm_arch_vcpu_load()), vCPU TSC device attributes (kvm_arch_tsc_set_attr()) and guest/host writing to TSC or TSC adjust MSR (kvm_set_msr_common()). The current x86 KVM implementation conflicts with protected TSC because the VMM can't change the TSC offset/multiplier. Because KVM emulates the TSC timer or the TSC deadline timer with the TSC offset/multiplier, the TSC timer interrupts is injected to the guest at the wrong time if the KVM TSC offset is different from what the TDX module determined. Originally this issue was found by cyclic test of rt-test [1] as the latency in TDX case is worse than VMX value + TDX SEAMCALL overhead. It turned out that the KVM TSC offset is different from what the TDX module determines. Disable or ignore the KVM logic to change/adjust the TSC offset/multiplier somehow, thus keeping the KVM TSC offset/multiplier the same as the value of the TDX module. Writes to MSR_IA32_TSC are also blocked as they amount to a change in the TSC offset. [1] https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git Reported-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> Message-ID: <3a7444aec08042fe205666864b6858910e86aa98.1728719037.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 5f3b30b commit adafea1

File tree

2 files changed

+10
-2
lines changed

2 files changed

+10
-2
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,7 @@ struct kvm_vcpu_arch {
10531053

10541054
/* Protected Guests */
10551055
bool guest_state_protected;
1056+
bool guest_tsc_protected;
10561057

10571058
/*
10581059
* Set when PDPTS were loaded directly by the userspace without

arch/x86/kvm/x86.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2569,6 +2569,9 @@ EXPORT_SYMBOL_GPL(kvm_calc_nested_tsc_multiplier);
25692569

25702570
static void kvm_vcpu_write_tsc_offset(struct kvm_vcpu *vcpu, u64 l1_offset)
25712571
{
2572+
if (vcpu->arch.guest_tsc_protected)
2573+
return;
2574+
25722575
trace_kvm_write_tsc_offset(vcpu->vcpu_id,
25732576
vcpu->arch.l1_tsc_offset,
25742577
l1_offset);
@@ -2632,6 +2635,9 @@ static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc,
26322635

26332636
lockdep_assert_held(&kvm->arch.tsc_write_lock);
26342637

2638+
if (vcpu->arch.guest_tsc_protected)
2639+
return;
2640+
26352641
if (user_set_tsc)
26362642
vcpu->kvm->arch.user_set_tsc = true;
26372643

@@ -3907,7 +3913,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
39073913
case MSR_IA32_TSC:
39083914
if (msr_info->host_initiated) {
39093915
kvm_synchronize_tsc(vcpu, &data);
3910-
} else {
3916+
} else if (!vcpu->arch.guest_tsc_protected) {
39113917
u64 adj = kvm_compute_l1_tsc_offset(vcpu, data) - vcpu->arch.l1_tsc_offset;
39123918
adjust_tsc_offset_guest(vcpu, adj);
39133919
vcpu->arch.ia32_tsc_adjust_msr += adj;
@@ -4987,7 +4993,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
49874993
u64 offset = kvm_compute_l1_tsc_offset(vcpu,
49884994
vcpu->arch.last_guest_tsc);
49894995
kvm_vcpu_write_tsc_offset(vcpu, offset);
4990-
vcpu->arch.tsc_catchup = 1;
4996+
if (!vcpu->arch.guest_tsc_protected)
4997+
vcpu->arch.tsc_catchup = 1;
49914998
}
49924999

49935000
if (kvm_lapic_hv_timer_in_use(vcpu))

0 commit comments

Comments
 (0)