aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/virtual/kvm/api.txt17
-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
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--include/uapi/linux/kvm.h1
10 files changed, 75 insertions, 7 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index d9ecceea5a02..43e0816d0de1 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -3627,6 +3627,23 @@ struct {
3627 3627
3628KVM handlers should exit to userspace with rc = -EREMOTE. 3628KVM handlers should exit to userspace with rc = -EREMOTE.
3629 3629
36307.5 KVM_CAP_SPLIT_IRQCHIP
3631
3632Architectures: x86
3633Parameters: None
3634Returns: 0 on success, -1 on error
3635
3636Create a local apic for each processor in the kernel. This can be used
3637instead of KVM_CREATE_IRQCHIP if the userspace VMM wishes to emulate the
3638IOAPIC and PIC (and also the PIT, even though this has to be enabled
3639separately).
3640
3641This supersedes KVM_CREATE_IRQCHIP, creating only local APICs, but no in kernel
3642IOAPIC or PIC. This also enables in kernel routing of interrupt requests.
3643
3644Fails if VCPU has already been created, or if the irqchip is already in the
3645kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
3646
3630 3647
36318. Other capabilities. 36488. Other capabilities.
3632---------------------- 3649----------------------
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)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 1bef9e21e725..354f147647ab 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1002,6 +1002,7 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
1002#endif 1002#endif
1003 1003
1004int kvm_setup_default_irq_routing(struct kvm *kvm); 1004int kvm_setup_default_irq_routing(struct kvm *kvm);
1005int kvm_setup_empty_irq_routing(struct kvm *kvm);
1005int kvm_set_irq_routing(struct kvm *kvm, 1006int kvm_set_irq_routing(struct kvm *kvm,
1006 const struct kvm_irq_routing_entry *entries, 1007 const struct kvm_irq_routing_entry *entries,
1007 unsigned nr, 1008 unsigned nr,
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index a9256f0331ae..ed00f8fc9ea2 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -824,6 +824,7 @@ struct kvm_ppc_smmu_info {
824#define KVM_CAP_MULTI_ADDRESS_SPACE 118 824#define KVM_CAP_MULTI_ADDRESS_SPACE 118
825#define KVM_CAP_GUEST_DEBUG_HW_BPS 119 825#define KVM_CAP_GUEST_DEBUG_HW_BPS 119
826#define KVM_CAP_GUEST_DEBUG_HW_WPS 120 826#define KVM_CAP_GUEST_DEBUG_HW_WPS 120
827#define KVM_CAP_SPLIT_IRQCHIP 121
827 828
828#ifdef KVM_CAP_IRQ_ROUTING 829#ifdef KVM_CAP_IRQ_ROUTING
829 830