Skip to content

Commit 6d5e3c3

Browse files
committed
Merge tag 'kvm-x86-misc-6.6' of https://github.com/kvm-x86/linux into HEAD
KVM x86 changes for 6.6: - Misc cleanups - Retry APIC optimized recalculation if a vCPU is added/enabled - Overhaul emergency reboot code to bring SVM up to par with VMX, tie the "emergency disabling" behavior to KVM actually being loaded, and move all of the logic within KVM - Fix user triggerable WARNs in SVM where KVM incorrectly assumes the TSC ratio MSR can diverge from the default iff TSC scaling is enabled, and clean up related code - Add a framework to allow "caching" feature flags so that KVM can check if the guest can use a feature without needing to search guest CPUID
2 parents bd7fe98 + 9717efb commit 6d5e3c3

28 files changed

+490
-445
lines changed

arch/x86/include/asm/kexec.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,6 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image);
205205
#endif
206206
#endif
207207

208-
typedef void crash_vmclear_fn(void);
209-
extern crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss;
210208
extern void kdump_nmi_shootdown_cpus(void);
211209

212210
#endif /* __ASSEMBLY__ */

arch/x86/include/asm/kvm_host.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,6 @@ struct kvm_vcpu_arch {
746746
u64 smi_count;
747747
bool at_instruction_boundary;
748748
bool tpr_access_reporting;
749-
bool xsaves_enabled;
750749
bool xfd_no_write_intercept;
751750
u64 ia32_xss;
752751
u64 microcode_version;
@@ -831,6 +830,25 @@ struct kvm_vcpu_arch {
831830
struct kvm_cpuid_entry2 *cpuid_entries;
832831
struct kvm_hypervisor_cpuid kvm_cpuid;
833832

833+
/*
834+
* FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly
835+
* when "struct kvm_vcpu_arch" is no longer defined in an
836+
* arch/x86/include/asm header. The max is mostly arbitrary, i.e.
837+
* can be increased as necessary.
838+
*/
839+
#define KVM_MAX_NR_GOVERNED_FEATURES BITS_PER_LONG
840+
841+
/*
842+
* Track whether or not the guest is allowed to use features that are
843+
* governed by KVM, where "governed" means KVM needs to manage state
844+
* and/or explicitly enable the feature in hardware. Typically, but
845+
* not always, governed features can be used by the guest if and only
846+
* if both KVM and userspace want to expose the feature to the guest.
847+
*/
848+
struct {
849+
DECLARE_BITMAP(enabled, KVM_MAX_NR_GOVERNED_FEATURES);
850+
} governed_features;
851+
834852
u64 reserved_gpa_bits;
835853
int maxphyaddr;
836854

@@ -1655,8 +1673,8 @@ struct kvm_x86_ops {
16551673

16561674
u64 (*get_l2_tsc_offset)(struct kvm_vcpu *vcpu);
16571675
u64 (*get_l2_tsc_multiplier)(struct kvm_vcpu *vcpu);
1658-
void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
1659-
void (*write_tsc_multiplier)(struct kvm_vcpu *vcpu, u64 multiplier);
1676+
void (*write_tsc_offset)(struct kvm_vcpu *vcpu);
1677+
void (*write_tsc_multiplier)(struct kvm_vcpu *vcpu);
16601678

16611679
/*
16621680
* Retrieve somewhat arbitrary exit information. Intended to

arch/x86/include/asm/reboot.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ void __noreturn machine_real_restart(unsigned int type);
2525
#define MRR_BIOS 0
2626
#define MRR_APM 1
2727

28+
#if IS_ENABLED(CONFIG_KVM_INTEL) || IS_ENABLED(CONFIG_KVM_AMD)
29+
typedef void (cpu_emergency_virt_cb)(void);
30+
void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback);
31+
void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback);
2832
void cpu_emergency_disable_virtualization(void);
33+
#else
34+
static inline void cpu_emergency_disable_virtualization(void) {}
35+
#endif /* CONFIG_KVM_INTEL || CONFIG_KVM_AMD */
2936

3037
typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
3138
void nmi_shootdown_cpus(nmi_shootdown_cb callback);

arch/x86/include/asm/virtext.h

Lines changed: 0 additions & 154 deletions
This file was deleted.

arch/x86/include/asm/vmx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
#define SECONDARY_EXEC_RDSEED_EXITING VMCS_CONTROL_BIT(RDSEED_EXITING)
7272
#define SECONDARY_EXEC_ENABLE_PML VMCS_CONTROL_BIT(PAGE_MOD_LOGGING)
7373
#define SECONDARY_EXEC_PT_CONCEAL_VMX VMCS_CONTROL_BIT(PT_CONCEAL_VMX)
74-
#define SECONDARY_EXEC_XSAVES VMCS_CONTROL_BIT(XSAVES)
74+
#define SECONDARY_EXEC_ENABLE_XSAVES VMCS_CONTROL_BIT(XSAVES)
7575
#define SECONDARY_EXEC_MODE_BASED_EPT_EXEC VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC)
7676
#define SECONDARY_EXEC_PT_USE_GPA VMCS_CONTROL_BIT(PT_USE_GPA)
7777
#define SECONDARY_EXEC_TSC_SCALING VMCS_CONTROL_BIT(TSC_SCALING)

arch/x86/kernel/crash.c

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -48,38 +48,12 @@ struct crash_memmap_data {
4848
unsigned int type;
4949
};
5050

51-
/*
52-
* This is used to VMCLEAR all VMCSs loaded on the
53-
* processor. And when loading kvm_intel module, the
54-
* callback function pointer will be assigned.
55-
*
56-
* protected by rcu.
57-
*/
58-
crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL;
59-
EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);
60-
61-
static inline void cpu_crash_vmclear_loaded_vmcss(void)
62-
{
63-
crash_vmclear_fn *do_vmclear_operation = NULL;
64-
65-
rcu_read_lock();
66-
do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss);
67-
if (do_vmclear_operation)
68-
do_vmclear_operation();
69-
rcu_read_unlock();
70-
}
71-
7251
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
7352

7453
static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
7554
{
7655
crash_save_cpu(regs, cpu);
7756

78-
/*
79-
* VMCLEAR VMCSs loaded on all cpus if needed.
80-
*/
81-
cpu_crash_vmclear_loaded_vmcss();
82-
8357
/*
8458
* Disable Intel PT to stop its logging
8559
*/
@@ -133,11 +107,6 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
133107

134108
crash_smp_send_stop();
135109

136-
/*
137-
* VMCLEAR VMCSs loaded on this cpu if needed.
138-
*/
139-
cpu_crash_vmclear_loaded_vmcss();
140-
141110
cpu_emergency_disable_virtualization();
142111

143112
/*

arch/x86/kernel/reboot.c

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <asm/reboot_fixups.h>
2323
#include <asm/reboot.h>
2424
#include <asm/pci_x86.h>
25-
#include <asm/virtext.h>
2625
#include <asm/cpu.h>
2726
#include <asm/nmi.h>
2827
#include <asm/smp.h>
@@ -530,9 +529,54 @@ static inline void kb_wait(void)
530529

531530
static inline void nmi_shootdown_cpus_on_restart(void);
532531

532+
#if IS_ENABLED(CONFIG_KVM_INTEL) || IS_ENABLED(CONFIG_KVM_AMD)
533+
/* RCU-protected callback to disable virtualization prior to reboot. */
534+
static cpu_emergency_virt_cb __rcu *cpu_emergency_virt_callback;
535+
536+
void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback)
537+
{
538+
if (WARN_ON_ONCE(rcu_access_pointer(cpu_emergency_virt_callback)))
539+
return;
540+
541+
rcu_assign_pointer(cpu_emergency_virt_callback, callback);
542+
}
543+
EXPORT_SYMBOL_GPL(cpu_emergency_register_virt_callback);
544+
545+
void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback)
546+
{
547+
if (WARN_ON_ONCE(rcu_access_pointer(cpu_emergency_virt_callback) != callback))
548+
return;
549+
550+
rcu_assign_pointer(cpu_emergency_virt_callback, NULL);
551+
synchronize_rcu();
552+
}
553+
EXPORT_SYMBOL_GPL(cpu_emergency_unregister_virt_callback);
554+
555+
/*
556+
* Disable virtualization, i.e. VMX or SVM, to ensure INIT is recognized during
557+
* reboot. VMX blocks INIT if the CPU is post-VMXON, and SVM blocks INIT if
558+
* GIF=0, i.e. if the crash occurred between CLGI and STGI.
559+
*/
560+
void cpu_emergency_disable_virtualization(void)
561+
{
562+
cpu_emergency_virt_cb *callback;
563+
564+
/*
565+
* IRQs must be disabled as KVM enables virtualization in hardware via
566+
* function call IPIs, i.e. IRQs need to be disabled to guarantee
567+
* virtualization stays disabled.
568+
*/
569+
lockdep_assert_irqs_disabled();
570+
571+
rcu_read_lock();
572+
callback = rcu_dereference(cpu_emergency_virt_callback);
573+
if (callback)
574+
callback();
575+
rcu_read_unlock();
576+
}
577+
533578
static void emergency_reboot_disable_virtualization(void)
534579
{
535-
/* Just make sure we won't change CPUs while doing this */
536580
local_irq_disable();
537581

538582
/*
@@ -545,15 +589,17 @@ static void emergency_reboot_disable_virtualization(void)
545589
* Do the NMI shootdown even if virtualization is off on _this_ CPU, as
546590
* other CPUs may have virtualization enabled.
547591
*/
548-
if (cpu_has_vmx() || cpu_has_svm(NULL)) {
592+
if (rcu_access_pointer(cpu_emergency_virt_callback)) {
549593
/* Safely force _this_ CPU out of VMX/SVM operation. */
550594
cpu_emergency_disable_virtualization();
551595

552596
/* Disable VMX/SVM and halt on other CPUs. */
553597
nmi_shootdown_cpus_on_restart();
554598
}
555599
}
556-
600+
#else
601+
static void emergency_reboot_disable_virtualization(void) { }
602+
#endif /* CONFIG_KVM_INTEL || CONFIG_KVM_AMD */
557603

558604
void __attribute__((weak)) mach_reboot_fixups(void)
559605
{
@@ -787,21 +833,9 @@ void machine_crash_shutdown(struct pt_regs *regs)
787833
}
788834
#endif
789835

790-
791836
/* This is the CPU performing the emergency shutdown work. */
792837
int crashing_cpu = -1;
793838

794-
/*
795-
* Disable virtualization, i.e. VMX or SVM, to ensure INIT is recognized during
796-
* reboot. VMX blocks INIT if the CPU is post-VMXON, and SVM blocks INIT if
797-
* GIF=0, i.e. if the crash occurred between CLGI and STGI.
798-
*/
799-
void cpu_emergency_disable_virtualization(void)
800-
{
801-
cpu_emergency_vmxoff();
802-
cpu_emergency_svm_disable();
803-
}
804-
805839
#if defined(CONFIG_SMP)
806840

807841
static nmi_shootdown_cb shootdown_callback;

arch/x86/kvm/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ config X86_SGX_KVM
101101

102102
config KVM_AMD
103103
tristate "KVM for AMD processors support"
104-
depends on KVM
104+
depends on KVM && (CPU_SUP_AMD || CPU_SUP_HYGON)
105105
help
106106
Provides support for KVM on AMD processors equipped with the AMD-V
107107
(SVM) extensions.

0 commit comments

Comments
 (0)