diff options
| -rw-r--r-- | drivers/kvm/kvm_main.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index ea027190a658..3226ad4bce7c 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
| @@ -50,8 +50,12 @@ MODULE_LICENSE("GPL"); | |||
| 50 | static DEFINE_SPINLOCK(kvm_lock); | 50 | static DEFINE_SPINLOCK(kvm_lock); |
| 51 | static LIST_HEAD(vm_list); | 51 | static LIST_HEAD(vm_list); |
| 52 | 52 | ||
| 53 | static cpumask_t cpus_hardware_enabled; | ||
| 54 | |||
| 53 | struct kvm_arch_ops *kvm_arch_ops; | 55 | struct kvm_arch_ops *kvm_arch_ops; |
| 54 | 56 | ||
| 57 | static void hardware_disable(void *ignored); | ||
| 58 | |||
| 55 | #define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x) | 59 | #define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x) |
| 56 | 60 | ||
| 57 | static struct kvm_stats_debugfs_item { | 61 | static struct kvm_stats_debugfs_item { |
| @@ -2930,7 +2934,7 @@ static int kvm_reboot(struct notifier_block *notifier, unsigned long val, | |||
| 2930 | * in vmx root mode. | 2934 | * in vmx root mode. |
| 2931 | */ | 2935 | */ |
| 2932 | printk(KERN_INFO "kvm: exiting hardware virtualization\n"); | 2936 | printk(KERN_INFO "kvm: exiting hardware virtualization\n"); |
| 2933 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | 2937 | on_each_cpu(hardware_disable, NULL, 0, 1); |
| 2934 | } | 2938 | } |
| 2935 | return NOTIFY_OK; | 2939 | return NOTIFY_OK; |
| 2936 | } | 2940 | } |
| @@ -2973,6 +2977,27 @@ static void decache_vcpus_on_cpu(int cpu) | |||
| 2973 | spin_unlock(&kvm_lock); | 2977 | spin_unlock(&kvm_lock); |
| 2974 | } | 2978 | } |
| 2975 | 2979 | ||
| 2980 | static void hardware_enable(void *junk) | ||
| 2981 | { | ||
| 2982 | int cpu = raw_smp_processor_id(); | ||
| 2983 | |||
| 2984 | if (cpu_isset(cpu, cpus_hardware_enabled)) | ||
| 2985 | return; | ||
| 2986 | cpu_set(cpu, cpus_hardware_enabled); | ||
| 2987 | kvm_arch_ops->hardware_enable(NULL); | ||
| 2988 | } | ||
| 2989 | |||
| 2990 | static void hardware_disable(void *junk) | ||
| 2991 | { | ||
| 2992 | int cpu = raw_smp_processor_id(); | ||
| 2993 | |||
| 2994 | if (!cpu_isset(cpu, cpus_hardware_enabled)) | ||
| 2995 | return; | ||
| 2996 | cpu_clear(cpu, cpus_hardware_enabled); | ||
| 2997 | decache_vcpus_on_cpu(cpu); | ||
| 2998 | kvm_arch_ops->hardware_disable(NULL); | ||
| 2999 | } | ||
| 3000 | |||
| 2976 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | 3001 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, |
| 2977 | void *v) | 3002 | void *v) |
| 2978 | { | 3003 | { |
| @@ -2985,16 +3010,13 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | |||
| 2985 | case CPU_UP_CANCELED_FROZEN: | 3010 | case CPU_UP_CANCELED_FROZEN: |
| 2986 | printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n", | 3011 | printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n", |
| 2987 | cpu); | 3012 | cpu); |
| 2988 | decache_vcpus_on_cpu(cpu); | 3013 | smp_call_function_single(cpu, hardware_disable, NULL, 0, 1); |
| 2989 | smp_call_function_single(cpu, kvm_arch_ops->hardware_disable, | ||
| 2990 | NULL, 0, 1); | ||
| 2991 | break; | 3014 | break; |
| 2992 | case CPU_ONLINE: | 3015 | case CPU_ONLINE: |
| 2993 | case CPU_ONLINE_FROZEN: | 3016 | case CPU_ONLINE_FROZEN: |
| 2994 | printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", | 3017 | printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", |
| 2995 | cpu); | 3018 | cpu); |
| 2996 | smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, | 3019 | smp_call_function_single(cpu, hardware_enable, NULL, 0, 1); |
| 2997 | NULL, 0, 1); | ||
| 2998 | break; | 3020 | break; |
| 2999 | } | 3021 | } |
| 3000 | return NOTIFY_OK; | 3022 | return NOTIFY_OK; |
| @@ -3088,14 +3110,13 @@ static void kvm_exit_debug(void) | |||
| 3088 | 3110 | ||
| 3089 | static int kvm_suspend(struct sys_device *dev, pm_message_t state) | 3111 | static int kvm_suspend(struct sys_device *dev, pm_message_t state) |
| 3090 | { | 3112 | { |
| 3091 | decache_vcpus_on_cpu(raw_smp_processor_id()); | 3113 | on_each_cpu(hardware_disable, NULL, 0, 0); |
| 3092 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | ||
| 3093 | return 0; | 3114 | return 0; |
| 3094 | } | 3115 | } |
| 3095 | 3116 | ||
| 3096 | static int kvm_resume(struct sys_device *dev) | 3117 | static int kvm_resume(struct sys_device *dev) |
| 3097 | { | 3118 | { |
| 3098 | on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); | 3119 | on_each_cpu(hardware_disable, NULL, 0, 0); |
| 3099 | return 0; | 3120 | return 0; |
| 3100 | } | 3121 | } |
| 3101 | 3122 | ||
| @@ -3136,7 +3157,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | |||
| 3136 | if (r < 0) | 3157 | if (r < 0) |
| 3137 | goto out; | 3158 | goto out; |
| 3138 | 3159 | ||
| 3139 | on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); | 3160 | on_each_cpu(hardware_enable, NULL, 0, 1); |
| 3140 | r = register_cpu_notifier(&kvm_cpu_notifier); | 3161 | r = register_cpu_notifier(&kvm_cpu_notifier); |
| 3141 | if (r) | 3162 | if (r) |
| 3142 | goto out_free_1; | 3163 | goto out_free_1; |
| @@ -3168,7 +3189,7 @@ out_free_2: | |||
| 3168 | unregister_reboot_notifier(&kvm_reboot_notifier); | 3189 | unregister_reboot_notifier(&kvm_reboot_notifier); |
| 3169 | unregister_cpu_notifier(&kvm_cpu_notifier); | 3190 | unregister_cpu_notifier(&kvm_cpu_notifier); |
| 3170 | out_free_1: | 3191 | out_free_1: |
| 3171 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | 3192 | on_each_cpu(hardware_disable, NULL, 0, 1); |
| 3172 | kvm_arch_ops->hardware_unsetup(); | 3193 | kvm_arch_ops->hardware_unsetup(); |
| 3173 | out: | 3194 | out: |
| 3174 | kvm_arch_ops = NULL; | 3195 | kvm_arch_ops = NULL; |
| @@ -3182,7 +3203,7 @@ void kvm_exit_arch(void) | |||
| 3182 | sysdev_class_unregister(&kvm_sysdev_class); | 3203 | sysdev_class_unregister(&kvm_sysdev_class); |
| 3183 | unregister_reboot_notifier(&kvm_reboot_notifier); | 3204 | unregister_reboot_notifier(&kvm_reboot_notifier); |
| 3184 | unregister_cpu_notifier(&kvm_cpu_notifier); | 3205 | unregister_cpu_notifier(&kvm_cpu_notifier); |
| 3185 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | 3206 | on_each_cpu(hardware_disable, NULL, 0, 1); |
| 3186 | kvm_arch_ops->hardware_unsetup(); | 3207 | kvm_arch_ops->hardware_unsetup(); |
| 3187 | kvm_arch_ops = NULL; | 3208 | kvm_arch_ops = NULL; |
| 3188 | } | 3209 | } |
