@@ -460,6 +460,7 @@ struct kvm_x86_ops {
int (*cpu_has_kvm_support)(void); /* __init */
int (*disabled_by_bios)(void); /* __init */
int (*cpu_hotadd)(int cpu);
+ void (*cpu_hotremove)(int cpu);
int (*hardware_enable)(void *dummy);
void (*hardware_disable)(void *dummy);
void (*check_processor_compatibility)(void *rtn);
@@ -2869,6 +2869,7 @@ static struct kvm_x86_ops svm_x86_ops = {
.hardware_unsetup = svm_hardware_unsetup,
.check_processor_compatibility = svm_check_processor_compat,
.cpu_hotadd = svm_cpu_hotadd,
+ .cpu_hotremove = svm_cpu_uninit,
.hardware_enable = svm_hardware_enable,
.hardware_disable = svm_hardware_disable,
.cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
@@ -1424,6 +1424,12 @@ static __cpuinit int vmx_cpu_hotadd(int cpu)
return 0;
}
+static __cpuinit void vmx_cpu_hotremove(int cpu)
+{
+ free_vmcs(per_cpu(vmxarea, cpu));
+ per_cpu(vmxarea, cpu) = NULL;
+}
+
static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
{
struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -3942,6 +3948,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
.hardware_unsetup = hardware_unsetup,
.check_processor_compatibility = vmx_check_processor_compat,
.cpu_hotadd = vmx_cpu_hotadd,
+ .cpu_hotremove = vmx_cpu_hotremove,
.hardware_enable = hardware_enable,
.hardware_disable = hardware_disable,
.cpu_has_accelerated_tpr = report_flexpriority,
@@ -4719,6 +4719,11 @@ int kvm_arch_cpu_hotadd(int cpu)
return kvm_x86_ops->cpu_hotadd(cpu);
}
+void kvm_arch_cpu_hotremove(int cpu)
+{
+ kvm_x86_ops->cpu_hotremove(cpu);
+}
+
int kvm_arch_hardware_enable(void *garbage)
{
/*
@@ -347,8 +347,10 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
#ifdef KVM_ARCH_WANT_HOTPLUG_NOTIFIER
int kvm_arch_cpu_hotadd(int cpu);
+void kvm_arch_cpu_hotremove(int cpu);
#else
#define kvm_arch_cpu_hotadd(x) (0)
+#define kvm_arch_cpu_hotremove(x)
#endif
int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu);
@@ -1725,11 +1725,13 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
cpu);
hardware_disable(NULL);
+ kvm_arch_cpu_hotremove(cpu);
break;
case CPU_UP_CANCELED:
printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
cpu);
smp_call_function_single(cpu, hardware_disable, NULL, 1);
+ kvm_arch_cpu_hotremove(cpu);
break;
case CPU_ONLINE:
printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
In the process of bringing down CPUs, the SVM / VMX structures associated with those CPUs are not freed. This may cause leaks when unloading and reloading the KVM module, as only the structures associated with online CPUs are cleaned up. Signed-off-by: Zachary Amsden <zamsden@redhat.com> --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/svm.c | 1 + arch/x86/kvm/vmx.c | 7 +++++++ arch/x86/kvm/x86.c | 5 +++++ include/linux/kvm_host.h | 2 ++ virt/kvm/kvm_main.c | 2 ++ 6 files changed, 18 insertions(+), 0 deletions(-)