Commit 938c8745 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: x86: Introduce "struct kvm_caps" to track misc caps/settings

Add kvm_caps to hold a variety of capabilites and defaults that aren't
handled by kvm_cpu_caps because they aren't CPUID bits in order to reduce
the amount of boilerplate code required to add a new feature.  The vast
majority (all?) of the caps interact with vendor code and are written
only during initialization, i.e. should be tagged __read_mostly, declared
extern in x86.h, and exported.

No functional change intended.
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Message-Id: <20220524135624.22988-4-chenyi.qiang@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 30267b43
...@@ -1664,21 +1664,6 @@ extern bool tdp_enabled; ...@@ -1664,21 +1664,6 @@ extern bool tdp_enabled;
u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu); u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
/* control of guest tsc rate supported? */
extern bool kvm_has_tsc_control;
/* maximum supported tsc_khz for guests */
extern u32 kvm_max_guest_tsc_khz;
/* number of bits of the fractional part of the TSC scaling ratio */
extern u8 kvm_tsc_scaling_ratio_frac_bits;
/* maximum allowed value of TSC scaling ratio */
extern u64 kvm_max_tsc_scaling_ratio;
/* 1ull << kvm_tsc_scaling_ratio_frac_bits */
extern u64 kvm_default_tsc_scaling_ratio;
/* bus lock detection supported? */
extern bool kvm_has_bus_lock_exit;
extern u64 kvm_mce_cap_supported;
/* /*
* EMULTYPE_NO_DECODE - Set when re-emulating an instruction (after completing * EMULTYPE_NO_DECODE - Set when re-emulating an instruction (after completing
* userspace I/O) to indicate that the emulation context * userspace I/O) to indicate that the emulation context
......
...@@ -200,7 +200,7 @@ void kvm_update_pv_runtime(struct kvm_vcpu *vcpu) ...@@ -200,7 +200,7 @@ void kvm_update_pv_runtime(struct kvm_vcpu *vcpu)
/* /*
* Calculate guest's supported XCR0 taking into account guest CPUID data and * Calculate guest's supported XCR0 taking into account guest CPUID data and
* supported_xcr0 (comprised of host configuration and KVM_SUPPORTED_XCR0). * KVM's supported XCR0 (comprised of host's XCR0 and KVM_SUPPORTED_XCR0).
*/ */
static u64 cpuid_get_supported_xcr0(struct kvm_cpuid_entry2 *entries, int nent) static u64 cpuid_get_supported_xcr0(struct kvm_cpuid_entry2 *entries, int nent)
{ {
...@@ -210,7 +210,7 @@ static u64 cpuid_get_supported_xcr0(struct kvm_cpuid_entry2 *entries, int nent) ...@@ -210,7 +210,7 @@ static u64 cpuid_get_supported_xcr0(struct kvm_cpuid_entry2 *entries, int nent)
if (!best) if (!best)
return 0; return 0;
return (best->eax | ((u64)best->edx << 32)) & supported_xcr0; return (best->eax | ((u64)best->edx << 32)) & kvm_caps.supported_xcr0;
} }
static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *entries, static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *entries,
...@@ -912,8 +912,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) ...@@ -912,8 +912,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
} }
break; break;
case 0xd: { case 0xd: {
u64 permitted_xcr0 = supported_xcr0 & xstate_get_guest_group_perm(); u64 permitted_xcr0 = kvm_caps.supported_xcr0 & xstate_get_guest_group_perm();
u64 permitted_xss = supported_xss; u64 permitted_xss = kvm_caps.supported_xss;
entry->eax &= permitted_xcr0; entry->eax &= permitted_xcr0;
entry->ebx = xstate_required_size(permitted_xcr0, false); entry->ebx = xstate_required_size(permitted_xcr0, false);
......
...@@ -48,7 +48,7 @@ DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_fops, vcpu_get_tsc_scaling_ratio, NULL, ...@@ -48,7 +48,7 @@ DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_fops, vcpu_get_tsc_scaling_ratio, NULL,
static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val) static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val)
{ {
*val = kvm_tsc_scaling_ratio_frac_bits; *val = kvm_caps.tsc_scaling_ratio_frac_bits;
return 0; return 0;
} }
...@@ -66,7 +66,7 @@ void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_ ...@@ -66,7 +66,7 @@ void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_
debugfs_dentry, vcpu, debugfs_dentry, vcpu,
&vcpu_timer_advance_ns_fops); &vcpu_timer_advance_ns_fops);
if (kvm_has_tsc_control) { if (kvm_caps.has_tsc_control) {
debugfs_create_file("tsc-scaling-ratio", 0444, debugfs_create_file("tsc-scaling-ratio", 0444,
debugfs_dentry, vcpu, debugfs_dentry, vcpu,
&vcpu_tsc_scaling_fops); &vcpu_tsc_scaling_fops);
......
...@@ -1603,7 +1603,7 @@ static inline void __wait_lapic_expire(struct kvm_vcpu *vcpu, u64 guest_cycles) ...@@ -1603,7 +1603,7 @@ static inline void __wait_lapic_expire(struct kvm_vcpu *vcpu, u64 guest_cycles)
* that __delay() uses delay_tsc whenever the hardware has TSC, thus * that __delay() uses delay_tsc whenever the hardware has TSC, thus
* always for VMX enabled hardware. * always for VMX enabled hardware.
*/ */
if (vcpu->arch.tsc_scaling_ratio == kvm_default_tsc_scaling_ratio) { if (vcpu->arch.tsc_scaling_ratio == kvm_caps.default_tsc_scaling_ratio) {
__delay(min(guest_cycles, __delay(min(guest_cycles,
nsec_to_cycles(vcpu, timer_advance_ns))); nsec_to_cycles(vcpu, timer_advance_ns)));
} else { } else {
......
...@@ -674,7 +674,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm, ...@@ -674,7 +674,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm,
vmcb02->control.tsc_offset = vcpu->arch.tsc_offset; vmcb02->control.tsc_offset = vcpu->arch.tsc_offset;
if (svm->tsc_ratio_msr != kvm_default_tsc_scaling_ratio) { if (svm->tsc_ratio_msr != kvm_caps.default_tsc_scaling_ratio) {
WARN_ON(!svm->tsc_scaling_enabled); WARN_ON(!svm->tsc_scaling_enabled);
nested_svm_update_tsc_ratio_msr(vcpu); nested_svm_update_tsc_ratio_msr(vcpu);
} }
...@@ -1031,7 +1031,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm) ...@@ -1031,7 +1031,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
vmcb_mark_dirty(vmcb01, VMCB_INTERCEPTS); vmcb_mark_dirty(vmcb01, VMCB_INTERCEPTS);
} }
if (svm->tsc_ratio_msr != kvm_default_tsc_scaling_ratio) { if (svm->tsc_ratio_msr != kvm_caps.default_tsc_scaling_ratio) {
WARN_ON(!svm->tsc_scaling_enabled); WARN_ON(!svm->tsc_scaling_enabled);
vcpu->arch.tsc_scaling_ratio = vcpu->arch.l1_tsc_scaling_ratio; vcpu->arch.tsc_scaling_ratio = vcpu->arch.l1_tsc_scaling_ratio;
__svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
......
...@@ -1285,7 +1285,7 @@ static void __svm_vcpu_reset(struct kvm_vcpu *vcpu) ...@@ -1285,7 +1285,7 @@ static void __svm_vcpu_reset(struct kvm_vcpu *vcpu)
svm_init_osvw(vcpu); svm_init_osvw(vcpu);
vcpu->arch.microcode_version = 0x01000065; vcpu->arch.microcode_version = 0x01000065;
svm->tsc_ratio_msr = kvm_default_tsc_scaling_ratio; svm->tsc_ratio_msr = kvm_caps.default_tsc_scaling_ratio;
if (sev_es_guest(vcpu->kvm)) if (sev_es_guest(vcpu->kvm))
sev_es_vcpu_reset(svm); sev_es_vcpu_reset(svm);
...@@ -4868,7 +4868,7 @@ static __init void svm_set_cpu_caps(void) ...@@ -4868,7 +4868,7 @@ static __init void svm_set_cpu_caps(void)
{ {
kvm_set_cpu_caps(); kvm_set_cpu_caps();
supported_xss = 0; kvm_caps.supported_xss = 0;
/* CPUID 0x80000001 and 0x8000000A (SVM features) */ /* CPUID 0x80000001 and 0x8000000A (SVM features) */
if (nested) { if (nested) {
...@@ -4944,7 +4944,8 @@ static __init int svm_hardware_setup(void) ...@@ -4944,7 +4944,8 @@ static __init int svm_hardware_setup(void)
init_msrpm_offsets(); init_msrpm_offsets();
supported_xcr0 &= ~(XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR); kvm_caps.supported_xcr0 &= ~(XFEATURE_MASK_BNDREGS |
XFEATURE_MASK_BNDCSR);
if (boot_cpu_has(X86_FEATURE_FXSR_OPT)) if (boot_cpu_has(X86_FEATURE_FXSR_OPT))
kvm_enable_efer_bits(EFER_FFXSR); kvm_enable_efer_bits(EFER_FFXSR);
...@@ -4954,11 +4955,11 @@ static __init int svm_hardware_setup(void) ...@@ -4954,11 +4955,11 @@ static __init int svm_hardware_setup(void)
tsc_scaling = false; tsc_scaling = false;
} else { } else {
pr_info("TSC scaling supported\n"); pr_info("TSC scaling supported\n");
kvm_has_tsc_control = true; kvm_caps.has_tsc_control = true;
} }
} }
kvm_max_tsc_scaling_ratio = SVM_TSC_RATIO_MAX; kvm_caps.max_tsc_scaling_ratio = SVM_TSC_RATIO_MAX;
kvm_tsc_scaling_ratio_frac_bits = 32; kvm_caps.tsc_scaling_ratio_frac_bits = 32;
tsc_aux_uret_slot = kvm_add_user_return_msr(MSR_TSC_AUX); tsc_aux_uret_slot = kvm_add_user_return_msr(MSR_TSC_AUX);
......
...@@ -2548,7 +2548,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, ...@@ -2548,7 +2548,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
vmx_get_l2_tsc_multiplier(vcpu)); vmx_get_l2_tsc_multiplier(vcpu));
vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset); vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
if (kvm_has_tsc_control) if (kvm_caps.has_tsc_control)
vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio); vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio);
nested_vmx_transition_tlb_flush(vcpu, vmcs12, true); nested_vmx_transition_tlb_flush(vcpu, vmcs12, true);
...@@ -4610,7 +4610,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, ...@@ -4610,7 +4610,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset); vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
if (kvm_has_tsc_control) if (kvm_caps.has_tsc_control)
vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio); vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio);
if (vmx->nested.l1_tpr_threshold != -1) if (vmx->nested.l1_tpr_threshold != -1)
......
...@@ -1717,7 +1717,7 @@ u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu) ...@@ -1717,7 +1717,7 @@ u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu)
nested_cpu_has2(vmcs12, SECONDARY_EXEC_TSC_SCALING)) nested_cpu_has2(vmcs12, SECONDARY_EXEC_TSC_SCALING))
return vmcs12->tsc_multiplier; return vmcs12->tsc_multiplier;
return kvm_default_tsc_scaling_ratio; return kvm_caps.default_tsc_scaling_ratio;
} }
static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
...@@ -7544,7 +7544,7 @@ static __init void vmx_set_cpu_caps(void) ...@@ -7544,7 +7544,7 @@ static __init void vmx_set_cpu_caps(void)
kvm_cpu_cap_set(X86_FEATURE_UMIP); kvm_cpu_cap_set(X86_FEATURE_UMIP);
/* CPUID 0xD.1 */ /* CPUID 0xD.1 */
supported_xss = 0; kvm_caps.supported_xss = 0;
if (!cpu_has_vmx_xsaves()) if (!cpu_has_vmx_xsaves())
kvm_cpu_cap_clear(X86_FEATURE_XSAVES); kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
...@@ -7685,9 +7685,9 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc, ...@@ -7685,9 +7685,9 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
delta_tsc = 0; delta_tsc = 0;
/* Convert to host delta tsc if tsc scaling is enabled */ /* Convert to host delta tsc if tsc scaling is enabled */
if (vcpu->arch.l1_tsc_scaling_ratio != kvm_default_tsc_scaling_ratio && if (vcpu->arch.l1_tsc_scaling_ratio != kvm_caps.default_tsc_scaling_ratio &&
delta_tsc && u64_shl_div_u64(delta_tsc, delta_tsc && u64_shl_div_u64(delta_tsc,
kvm_tsc_scaling_ratio_frac_bits, kvm_caps.tsc_scaling_ratio_frac_bits,
vcpu->arch.l1_tsc_scaling_ratio, &delta_tsc)) vcpu->arch.l1_tsc_scaling_ratio, &delta_tsc))
return -ERANGE; return -ERANGE;
...@@ -8064,7 +8064,7 @@ static __init int hardware_setup(void) ...@@ -8064,7 +8064,7 @@ static __init int hardware_setup(void)
} }
if (!cpu_has_vmx_mpx()) if (!cpu_has_vmx_mpx())
supported_xcr0 &= ~(XFEATURE_MASK_BNDREGS | kvm_caps.supported_xcr0 &= ~(XFEATURE_MASK_BNDREGS |
XFEATURE_MASK_BNDCSR); XFEATURE_MASK_BNDCSR);
if (!cpu_has_vmx_vpid() || !cpu_has_vmx_invvpid() || if (!cpu_has_vmx_vpid() || !cpu_has_vmx_invvpid() ||
...@@ -8132,11 +8132,11 @@ static __init int hardware_setup(void) ...@@ -8132,11 +8132,11 @@ static __init int hardware_setup(void)
enable_ipiv = false; enable_ipiv = false;
if (cpu_has_vmx_tsc_scaling()) if (cpu_has_vmx_tsc_scaling())
kvm_has_tsc_control = true; kvm_caps.has_tsc_control = true;
kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX; kvm_caps.max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
kvm_tsc_scaling_ratio_frac_bits = 48; kvm_caps.tsc_scaling_ratio_frac_bits = 48;
kvm_has_bus_lock_exit = cpu_has_vmx_bus_lock_detection(); kvm_caps.has_bus_lock_exit = cpu_has_vmx_bus_lock_detection();
set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */ set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
...@@ -8193,7 +8193,7 @@ static __init int hardware_setup(void) ...@@ -8193,7 +8193,7 @@ static __init int hardware_setup(void)
vmx_x86_ops.request_immediate_exit = __kvm_request_immediate_exit; vmx_x86_ops.request_immediate_exit = __kvm_request_immediate_exit;
} }
kvm_mce_cap_supported |= MCG_LMCE_P; kvm_caps.supported_mce_cap |= MCG_LMCE_P;
if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST) if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST)
return -EINVAL; return -EINVAL;
......
This diff is collapsed.
...@@ -8,6 +8,25 @@ ...@@ -8,6 +8,25 @@
#include "kvm_cache_regs.h" #include "kvm_cache_regs.h"
#include "kvm_emulate.h" #include "kvm_emulate.h"
struct kvm_caps {
/* control of guest tsc rate supported? */
bool has_tsc_control;
/* maximum supported tsc_khz for guests */
u32 max_guest_tsc_khz;
/* number of bits of the fractional part of the TSC scaling ratio */
u8 tsc_scaling_ratio_frac_bits;
/* maximum allowed value of TSC scaling ratio */
u64 max_tsc_scaling_ratio;
/* 1ull << kvm_caps.tsc_scaling_ratio_frac_bits */
u64 default_tsc_scaling_ratio;
/* bus lock detection supported? */
bool has_bus_lock_exit;
u64 supported_mce_cap;
u64 supported_xcr0;
u64 supported_xss;
};
void kvm_spurious_fault(void); void kvm_spurious_fault(void);
#define KVM_NESTED_VMENTER_CONSISTENCY_CHECK(consistency_check) \ #define KVM_NESTED_VMENTER_CONSISTENCY_CHECK(consistency_check) \
...@@ -283,14 +302,15 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, ...@@ -283,14 +302,15 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu); fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu);
extern u64 host_xcr0; extern u64 host_xcr0;
extern u64 supported_xcr0;
extern u64 host_xss; extern u64 host_xss;
extern u64 supported_xss;
extern struct kvm_caps kvm_caps;
extern bool enable_pmu; extern bool enable_pmu;
static inline bool kvm_mpx_supported(void) static inline bool kvm_mpx_supported(void)
{ {
return (supported_xcr0 & (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR)) return (kvm_caps.supported_xcr0 & (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR))
== (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR); == (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment