Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'kvm-pre-tdx' into HEAD

- Add common secure TSC infrastructure for use within SNP and in the
future TDX

- Block KVM_CAP_SYNC_REGS if guest state is protected. It does not make
sense to use the capability if the relevant registers are not
available for reading or writing.

+28 -13
+1
arch/x86/include/asm/kvm_host.h
··· 1056 1056 1057 1057 /* Protected Guests */ 1058 1058 bool guest_state_protected; 1059 + bool guest_tsc_protected; 1059 1060 1060 1061 /* 1061 1062 * Set when PDPTS were loaded directly by the userspace without
+27 -13
arch/x86/kvm/x86.c
··· 2574 2574 2575 2575 static void kvm_vcpu_write_tsc_offset(struct kvm_vcpu *vcpu, u64 l1_offset) 2576 2576 { 2577 + if (vcpu->arch.guest_tsc_protected) 2578 + return; 2579 + 2577 2580 trace_kvm_write_tsc_offset(vcpu->vcpu_id, 2578 2581 vcpu->arch.l1_tsc_offset, 2579 2582 l1_offset); ··· 2634 2631 * participates in. 2635 2632 */ 2636 2633 static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc, 2637 - u64 ns, bool matched) 2634 + u64 ns, bool matched, bool user_set_tsc) 2638 2635 { 2639 2636 struct kvm *kvm = vcpu->kvm; 2640 2637 2641 2638 lockdep_assert_held(&kvm->arch.tsc_write_lock); 2639 + 2640 + if (vcpu->arch.guest_tsc_protected) 2641 + return; 2642 + 2643 + if (user_set_tsc) 2644 + vcpu->kvm->arch.user_set_tsc = true; 2642 2645 2643 2646 /* 2644 2647 * We also track th most recent recorded KHZ, write and time to ··· 2731 2722 } 2732 2723 } 2733 2724 2734 - if (user_value) 2735 - kvm->arch.user_set_tsc = true; 2736 2725 2737 2726 /* 2738 2727 * For a reliable TSC, we can match TSC offsets, and for an unstable ··· 2750 2743 matched = true; 2751 2744 } 2752 2745 2753 - __kvm_synchronize_tsc(vcpu, offset, data, ns, matched); 2746 + __kvm_synchronize_tsc(vcpu, offset, data, ns, matched, !!user_value); 2754 2747 raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); 2755 2748 } 2756 2749 ··· 3930 3923 case MSR_IA32_TSC: 3931 3924 if (msr_info->host_initiated) { 3932 3925 kvm_synchronize_tsc(vcpu, &data); 3933 - } else { 3926 + } else if (!vcpu->arch.guest_tsc_protected) { 3934 3927 u64 adj = kvm_compute_l1_tsc_offset(vcpu, data) - vcpu->arch.l1_tsc_offset; 3935 3928 adjust_tsc_offset_guest(vcpu, adj); 3936 3929 vcpu->arch.ia32_tsc_adjust_msr += adj; ··· 4597 4590 return type < 32 && (kvm_caps.supported_vm_types & BIT(type)); 4598 4591 } 4599 4592 4593 + static inline u32 kvm_sync_valid_fields(struct kvm *kvm) 4594 + { 4595 + return kvm && kvm->arch.has_protected_state ? 0 : KVM_SYNC_X86_VALID_FIELDS; 4596 + } 4597 + 4600 4598 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) 4601 4599 { 4602 4600 int r = 0; ··· 4710 4698 break; 4711 4699 #endif 4712 4700 case KVM_CAP_SYNC_REGS: 4713 - r = KVM_SYNC_X86_VALID_FIELDS; 4701 + r = kvm_sync_valid_fields(kvm); 4714 4702 break; 4715 4703 case KVM_CAP_ADJUST_CLOCK: 4716 4704 r = KVM_CLOCK_VALID_FLAGS; ··· 5015 5003 u64 offset = kvm_compute_l1_tsc_offset(vcpu, 5016 5004 vcpu->arch.last_guest_tsc); 5017 5005 kvm_vcpu_write_tsc_offset(vcpu, offset); 5018 - vcpu->arch.tsc_catchup = 1; 5006 + if (!vcpu->arch.guest_tsc_protected) 5007 + vcpu->arch.tsc_catchup = 1; 5019 5008 } 5020 5009 5021 5010 if (kvm_lapic_hv_timer_in_use(vcpu)) ··· 5755 5742 tsc = kvm_scale_tsc(rdtsc(), vcpu->arch.l1_tsc_scaling_ratio) + offset; 5756 5743 ns = get_kvmclock_base_ns(); 5757 5744 5758 - kvm->arch.user_set_tsc = true; 5759 - __kvm_synchronize_tsc(vcpu, offset, tsc, ns, matched); 5745 + __kvm_synchronize_tsc(vcpu, offset, tsc, ns, matched, true); 5760 5746 raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); 5761 5747 5762 5748 r = 0; ··· 11492 11480 { 11493 11481 struct kvm_queued_exception *ex = &vcpu->arch.exception; 11494 11482 struct kvm_run *kvm_run = vcpu->run; 11483 + u32 sync_valid_fields; 11495 11484 int r; 11496 11485 11497 11486 r = kvm_mmu_post_init_vm(vcpu->kvm); ··· 11538 11525 goto out; 11539 11526 } 11540 11527 11541 - if ((kvm_run->kvm_valid_regs & ~KVM_SYNC_X86_VALID_FIELDS) || 11542 - (kvm_run->kvm_dirty_regs & ~KVM_SYNC_X86_VALID_FIELDS)) { 11528 + sync_valid_fields = kvm_sync_valid_fields(vcpu->kvm); 11529 + if ((kvm_run->kvm_valid_regs & ~sync_valid_fields) || 11530 + (kvm_run->kvm_dirty_regs & ~sync_valid_fields)) { 11543 11531 r = -EINVAL; 11544 11532 goto out; 11545 11533 } ··· 11598 11584 11599 11585 out: 11600 11586 kvm_put_guest_fpu(vcpu); 11601 - if (kvm_run->kvm_valid_regs) 11587 + if (kvm_run->kvm_valid_regs && likely(!vcpu->arch.guest_state_protected)) 11602 11588 store_regs(vcpu); 11603 11589 post_kvm_run_save(vcpu); 11604 11590 kvm_vcpu_srcu_read_unlock(vcpu); ··· 12888 12874 mutex_unlock(&kvm->slots_lock); 12889 12875 } 12890 12876 kvm_destroy_vcpus(kvm); 12891 - kvm_x86_call(vm_destroy)(kvm); 12892 12877 kvm_free_msr_filter(srcu_dereference_check(kvm->arch.msr_filter, &kvm->srcu, 1)); 12893 12878 kvm_pic_destroy(kvm); 12894 12879 kvm_ioapic_destroy(kvm); ··· 12897 12884 kvm_page_track_cleanup(kvm); 12898 12885 kvm_xen_destroy_vm(kvm); 12899 12886 kvm_hv_destroy_vm(kvm); 12887 + kvm_x86_call(vm_destroy)(kvm); 12900 12888 } 12901 12889 12902 12890 static void memslot_rmap_free(struct kvm_memory_slot *slot)