diff options
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/irq.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/irq_comm.c | 15 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 11 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | virt/kvm/irqchip.c | 5 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 5 |
7 files changed, 19 insertions, 21 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 84c8489531bb..f5bddf92faba 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -728,7 +728,6 @@ struct kvm_hv { | |||
728 | 728 | ||
729 | enum kvm_irqchip_mode { | 729 | enum kvm_irqchip_mode { |
730 | KVM_IRQCHIP_NONE, | 730 | KVM_IRQCHIP_NONE, |
731 | KVM_IRQCHIP_INIT_IN_PROGRESS, /* temporarily set during creation */ | ||
732 | KVM_IRQCHIP_KERNEL, /* created with KVM_CREATE_IRQCHIP */ | 731 | KVM_IRQCHIP_KERNEL, /* created with KVM_CREATE_IRQCHIP */ |
733 | KVM_IRQCHIP_SPLIT, /* created with KVM_CAP_SPLIT_IRQCHIP */ | 732 | KVM_IRQCHIP_SPLIT, /* created with KVM_CAP_SPLIT_IRQCHIP */ |
734 | }; | 733 | }; |
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index 0edd22c3344c..d5005cc26521 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h | |||
@@ -111,7 +111,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm) | |||
111 | 111 | ||
112 | /* Matches smp_wmb() when setting irqchip_mode */ | 112 | /* Matches smp_wmb() when setting irqchip_mode */ |
113 | smp_rmb(); | 113 | smp_rmb(); |
114 | return mode > KVM_IRQCHIP_INIT_IN_PROGRESS; | 114 | return mode != KVM_IRQCHIP_NONE; |
115 | } | 115 | } |
116 | 116 | ||
117 | void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu); | 117 | void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu); |
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index 4517a4c2ac3a..3cc3b2d130a0 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c | |||
@@ -274,16 +274,19 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, | |||
274 | srcu_read_unlock(&kvm->irq_srcu, idx); | 274 | srcu_read_unlock(&kvm->irq_srcu, idx); |
275 | } | 275 | } |
276 | 276 | ||
277 | bool kvm_arch_can_set_irq_routing(struct kvm *kvm) | ||
278 | { | ||
279 | return irqchip_in_kernel(kvm); | ||
280 | } | ||
281 | |||
277 | int kvm_set_routing_entry(struct kvm *kvm, | 282 | int kvm_set_routing_entry(struct kvm *kvm, |
278 | struct kvm_kernel_irq_routing_entry *e, | 283 | struct kvm_kernel_irq_routing_entry *e, |
279 | const struct kvm_irq_routing_entry *ue) | 284 | const struct kvm_irq_routing_entry *ue) |
280 | { | 285 | { |
281 | /* also allow creation of routes during KVM_IRQCHIP_INIT_IN_PROGRESS */ | 286 | /* We can't check irqchip_in_kernel() here as some callers are |
282 | if (kvm->arch.irqchip_mode == KVM_IRQCHIP_NONE) | 287 | * currently inititalizing the irqchip. Other callers should therefore |
283 | return -EINVAL; | 288 | * check kvm_arch_can_set_irq_routing() before calling this function. |
284 | 289 | */ | |
285 | /* Matches smp_wmb() when setting irqchip_mode */ | ||
286 | smp_rmb(); | ||
287 | switch (ue->type) { | 290 | switch (ue->type) { |
288 | case KVM_IRQ_ROUTING_IRQCHIP: | 291 | case KVM_IRQ_ROUTING_IRQCHIP: |
289 | if (irqchip_split(kvm)) | 292 | if (irqchip_split(kvm)) |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index be2ade58edb9..2fe9aa116288 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -3919,14 +3919,9 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, | |||
3919 | goto split_irqchip_unlock; | 3919 | goto split_irqchip_unlock; |
3920 | if (kvm->created_vcpus) | 3920 | if (kvm->created_vcpus) |
3921 | goto split_irqchip_unlock; | 3921 | goto split_irqchip_unlock; |
3922 | kvm->arch.irqchip_mode = KVM_IRQCHIP_INIT_IN_PROGRESS; | ||
3923 | r = kvm_setup_empty_irq_routing(kvm); | 3922 | r = kvm_setup_empty_irq_routing(kvm); |
3924 | if (r) { | 3923 | if (r) |
3925 | kvm->arch.irqchip_mode = KVM_IRQCHIP_NONE; | ||
3926 | /* Pairs with smp_rmb() when reading irqchip_mode */ | ||
3927 | smp_wmb(); | ||
3928 | goto split_irqchip_unlock; | 3924 | goto split_irqchip_unlock; |
3929 | } | ||
3930 | /* Pairs with irqchip_in_kernel. */ | 3925 | /* Pairs with irqchip_in_kernel. */ |
3931 | smp_wmb(); | 3926 | smp_wmb(); |
3932 | kvm->arch.irqchip_mode = KVM_IRQCHIP_SPLIT; | 3927 | kvm->arch.irqchip_mode = KVM_IRQCHIP_SPLIT; |
@@ -4012,12 +4007,8 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
4012 | goto create_irqchip_unlock; | 4007 | goto create_irqchip_unlock; |
4013 | } | 4008 | } |
4014 | 4009 | ||
4015 | kvm->arch.irqchip_mode = KVM_IRQCHIP_INIT_IN_PROGRESS; | ||
4016 | r = kvm_setup_default_irq_routing(kvm); | 4010 | r = kvm_setup_default_irq_routing(kvm); |
4017 | if (r) { | 4011 | if (r) { |
4018 | kvm->arch.irqchip_mode = KVM_IRQCHIP_NONE; | ||
4019 | /* Pairs with smp_rmb() when reading irqchip_mode */ | ||
4020 | smp_wmb(); | ||
4021 | kvm_ioapic_destroy(kvm); | 4012 | kvm_ioapic_destroy(kvm); |
4022 | kvm_pic_destroy(kvm); | 4013 | kvm_pic_destroy(kvm); |
4023 | goto create_irqchip_unlock; | 4014 | goto create_irqchip_unlock; |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a5bfffa8c8d4..25cf258a1c9b 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -1018,6 +1018,7 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) | |||
1018 | #define KVM_MAX_IRQ_ROUTES 1024 | 1018 | #define KVM_MAX_IRQ_ROUTES 1024 |
1019 | #endif | 1019 | #endif |
1020 | 1020 | ||
1021 | bool kvm_arch_can_set_irq_routing(struct kvm *kvm); | ||
1021 | int kvm_set_irq_routing(struct kvm *kvm, | 1022 | int kvm_set_irq_routing(struct kvm *kvm, |
1022 | const struct kvm_irq_routing_entry *entries, | 1023 | const struct kvm_irq_routing_entry *entries, |
1023 | unsigned nr, | 1024 | unsigned nr, |
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c index cc30d01a56be..31e40c9e81df 100644 --- a/virt/kvm/irqchip.c +++ b/virt/kvm/irqchip.c | |||
@@ -172,6 +172,11 @@ void __attribute__((weak)) kvm_arch_irq_routing_update(struct kvm *kvm) | |||
172 | { | 172 | { |
173 | } | 173 | } |
174 | 174 | ||
175 | bool __weak kvm_arch_can_set_irq_routing(struct kvm *kvm) | ||
176 | { | ||
177 | return true; | ||
178 | } | ||
179 | |||
175 | int kvm_set_irq_routing(struct kvm *kvm, | 180 | int kvm_set_irq_routing(struct kvm *kvm, |
176 | const struct kvm_irq_routing_entry *ue, | 181 | const struct kvm_irq_routing_entry *ue, |
177 | unsigned nr, | 182 | unsigned nr, |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 035bc51f656f..6281cc2446d5 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -3075,6 +3075,8 @@ static long kvm_vm_ioctl(struct file *filp, | |||
3075 | if (copy_from_user(&routing, argp, sizeof(routing))) | 3075 | if (copy_from_user(&routing, argp, sizeof(routing))) |
3076 | goto out; | 3076 | goto out; |
3077 | r = -EINVAL; | 3077 | r = -EINVAL; |
3078 | if (!kvm_arch_can_set_irq_routing(kvm)) | ||
3079 | goto out; | ||
3078 | if (routing.nr > KVM_MAX_IRQ_ROUTES) | 3080 | if (routing.nr > KVM_MAX_IRQ_ROUTES) |
3079 | goto out; | 3081 | goto out; |
3080 | if (routing.flags) | 3082 | if (routing.flags) |
@@ -3090,11 +3092,8 @@ static long kvm_vm_ioctl(struct file *filp, | |||
3090 | routing.nr * sizeof(*entries))) | 3092 | routing.nr * sizeof(*entries))) |
3091 | goto out_free_irq_routing; | 3093 | goto out_free_irq_routing; |
3092 | } | 3094 | } |
3093 | /* avoid races with KVM_CREATE_IRQCHIP on x86 */ | ||
3094 | mutex_lock(&kvm->lock); | ||
3095 | r = kvm_set_irq_routing(kvm, entries, routing.nr, | 3095 | r = kvm_set_irq_routing(kvm, entries, routing.nr, |
3096 | routing.flags); | 3096 | routing.flags); |
3097 | mutex_unlock(&kvm->lock); | ||
3098 | out_free_irq_routing: | 3097 | out_free_irq_routing: |
3099 | vfree(entries); | 3098 | vfree(entries); |
3100 | break; | 3099 | break; |