aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/kvm_host.h2
-rw-r--r--arch/x86/kvm/i8254.c4
-rw-r--r--arch/x86/kvm/ioapic.h8
-rw-r--r--arch/x86/kvm/irq.h11
-rw-r--r--arch/x86/kvm/irq_comm.c9
-rw-r--r--arch/x86/kvm/lapic.c6
-rw-r--r--arch/x86/kvm/x86.c23
7 files changed, 56 insertions, 7 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a0ef289d5a86..befcf555bddc 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -684,6 +684,8 @@ struct kvm_arch {
684 u32 bsp_vcpu_id; 684 u32 bsp_vcpu_id;
685 685
686 u64 disabled_quirks; 686 u64 disabled_quirks;
687
688 bool irqchip_split;
687}; 689};
688 690
689struct kvm_vm_stat { 691struct kvm_vm_stat {
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index f90952f64e79..08116ff227cc 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -35,6 +35,7 @@
35#include <linux/kvm_host.h> 35#include <linux/kvm_host.h>
36#include <linux/slab.h> 36#include <linux/slab.h>
37 37
38#include "ioapic.h"
38#include "irq.h" 39#include "irq.h"
39#include "i8254.h" 40#include "i8254.h"
40#include "x86.h" 41#include "x86.h"
@@ -333,7 +334,8 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
333 struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; 334 struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
334 s64 interval; 335 s64 interval;
335 336
336 if (!irqchip_in_kernel(kvm) || ps->flags & KVM_PIT_FLAGS_HPET_LEGACY) 337 if (!ioapic_in_kernel(kvm) ||
338 ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
337 return; 339 return;
338 340
339 interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); 341 interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h
index bf36d66a1951..a8842c0dee73 100644
--- a/arch/x86/kvm/ioapic.h
+++ b/arch/x86/kvm/ioapic.h
@@ -97,6 +97,14 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
97 return kvm->arch.vioapic; 97 return kvm->arch.vioapic;
98} 98}
99 99
100static inline int ioapic_in_kernel(struct kvm *kvm)
101{
102 int ret;
103
104 ret = (ioapic_irqchip(kvm) != NULL);
105 return ret;
106}
107
100void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu); 108void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu);
101bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, 109bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
102 int short_hand, unsigned int dest, int dest_mode); 110 int short_hand, unsigned int dest, int dest_mode);
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 9e6e7e04de98..2f9703dcd913 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -83,13 +83,22 @@ static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
83 return kvm->arch.vpic; 83 return kvm->arch.vpic;
84} 84}
85 85
86static inline int irqchip_split(struct kvm *kvm)
87{
88 return kvm->arch.irqchip_split;
89}
90
86static inline int irqchip_in_kernel(struct kvm *kvm) 91static inline int irqchip_in_kernel(struct kvm *kvm)
87{ 92{
88 struct kvm_pic *vpic = pic_irqchip(kvm); 93 struct kvm_pic *vpic = pic_irqchip(kvm);
94 bool ret;
95
96 ret = (vpic != NULL);
97 ret |= irqchip_split(kvm);
89 98
90 /* Read vpic before kvm->irq_routing. */ 99 /* Read vpic before kvm->irq_routing. */
91 smp_rmb(); 100 smp_rmb();
92 return vpic != NULL; 101 return ret;
93} 102}
94 103
95static inline int lapic_in_kernel(struct kvm_vcpu *vcpu) 104static inline int lapic_in_kernel(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 9efff9e5b58c..67f6b62a6814 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -208,7 +208,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)
208 goto unlock; 208 goto unlock;
209 } 209 }
210 clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); 210 clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
211 if (!irqchip_in_kernel(kvm)) 211 if (!ioapic_in_kernel(kvm))
212 goto unlock; 212 goto unlock;
213 213
214 kvm_ioapic_clear_all(kvm->arch.vioapic, irq_source_id); 214 kvm_ioapic_clear_all(kvm->arch.vioapic, irq_source_id);
@@ -328,3 +328,10 @@ int kvm_setup_default_irq_routing(struct kvm *kvm)
328 return kvm_set_irq_routing(kvm, default_routing, 328 return kvm_set_irq_routing(kvm, default_routing,
329 ARRAY_SIZE(default_routing), 0); 329 ARRAY_SIZE(default_routing), 0);
330} 330}
331
332static const struct kvm_irq_routing_entry empty_routing[] = {};
333
334int kvm_setup_empty_irq_routing(struct kvm *kvm)
335{
336 return kvm_set_irq_routing(kvm, empty_routing, 0, 0);
337}
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index c4bcc86d6dc4..e05946c36b87 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -209,7 +209,8 @@ out:
209 if (old) 209 if (old)
210 kfree_rcu(old, rcu); 210 kfree_rcu(old, rcu);
211 211
212 kvm_vcpu_request_scan_ioapic(kvm); 212 if (ioapic_in_kernel(kvm))
213 kvm_vcpu_request_scan_ioapic(kvm);
213} 214}
214 215
215static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val) 216static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
@@ -1845,7 +1846,8 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu,
1845 kvm_x86_ops->hwapic_isr_update(vcpu->kvm, 1846 kvm_x86_ops->hwapic_isr_update(vcpu->kvm,
1846 apic_find_highest_isr(apic)); 1847 apic_find_highest_isr(apic));
1847 kvm_make_request(KVM_REQ_EVENT, vcpu); 1848 kvm_make_request(KVM_REQ_EVENT, vcpu);
1848 kvm_rtc_eoi_tracking_restore_one(vcpu); 1849 if (ioapic_in_kernel(vcpu->kvm))
1850 kvm_rtc_eoi_tracking_restore_one(vcpu);
1849} 1851}
1850 1852
1851void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) 1853void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 28c98c8f9d1c..f720774a4797 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2448,6 +2448,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
2448 case KVM_CAP_ENABLE_CAP_VM: 2448 case KVM_CAP_ENABLE_CAP_VM:
2449 case KVM_CAP_DISABLE_QUIRKS: 2449 case KVM_CAP_DISABLE_QUIRKS:
2450 case KVM_CAP_SET_BOOT_CPU_ID: 2450 case KVM_CAP_SET_BOOT_CPU_ID:
2451 case KVM_CAP_SPLIT_IRQCHIP:
2451#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT 2452#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
2452 case KVM_CAP_ASSIGN_DEV_IRQ: 2453 case KVM_CAP_ASSIGN_DEV_IRQ:
2453 case KVM_CAP_PCI_2_3: 2454 case KVM_CAP_PCI_2_3:
@@ -3555,6 +3556,24 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
3555 kvm->arch.disabled_quirks = cap->args[0]; 3556 kvm->arch.disabled_quirks = cap->args[0];
3556 r = 0; 3557 r = 0;
3557 break; 3558 break;
3559 case KVM_CAP_SPLIT_IRQCHIP: {
3560 mutex_lock(&kvm->lock);
3561 r = -EEXIST;
3562 if (irqchip_in_kernel(kvm))
3563 goto split_irqchip_unlock;
3564 if (atomic_read(&kvm->online_vcpus))
3565 goto split_irqchip_unlock;
3566 r = kvm_setup_empty_irq_routing(kvm);
3567 if (r)
3568 goto split_irqchip_unlock;
3569 /* Pairs with irqchip_in_kernel. */
3570 smp_wmb();
3571 kvm->arch.irqchip_split = true;
3572 r = 0;
3573split_irqchip_unlock:
3574 mutex_unlock(&kvm->lock);
3575 break;
3576 }
3558 default: 3577 default:
3559 r = -EINVAL; 3578 r = -EINVAL;
3560 break; 3579 break;
@@ -3668,7 +3687,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
3668 } 3687 }
3669 3688
3670 r = -ENXIO; 3689 r = -ENXIO;
3671 if (!irqchip_in_kernel(kvm)) 3690 if (!irqchip_in_kernel(kvm) || irqchip_split(kvm))
3672 goto get_irqchip_out; 3691 goto get_irqchip_out;
3673 r = kvm_vm_ioctl_get_irqchip(kvm, chip); 3692 r = kvm_vm_ioctl_get_irqchip(kvm, chip);
3674 if (r) 3693 if (r)
@@ -3692,7 +3711,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
3692 } 3711 }
3693 3712
3694 r = -ENXIO; 3713 r = -ENXIO;
3695 if (!irqchip_in_kernel(kvm)) 3714 if (!irqchip_in_kernel(kvm) || irqchip_split(kvm))
3696 goto set_irqchip_out; 3715 goto set_irqchip_out;
3697 r = kvm_vm_ioctl_set_irqchip(kvm, chip); 3716 r = kvm_vm_ioctl_set_irqchip(kvm, chip);
3698 if (r) 3717 if (r)