aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2012-02-28 08:19:54 -0500
committerAvi Kivity <avi@redhat.com>2012-03-08 07:11:36 -0500
commit07700a94b00a4fcbbfb07d1b72dc112a0e036735 (patch)
treee4a8045d6a44906463102a04c7a87337c38e16aa
parent3e515705a1f46beb1c942bb8043c16f8ac7b1e9e (diff)
KVM: Allow host IRQ sharing for assigned PCI 2.3 devices
PCI 2.3 allows to generically disable IRQ sources at device level. This enables us to share legacy IRQs of such devices with other host devices when passing them to a guest. The new IRQ sharing feature introduced here is optional, user space has to request it explicitly. Moreover, user space can inform us about its view of PCI_COMMAND_INTX_DISABLE so that we can avoid unmasking the interrupt and signaling it if the guest masked it via the virtualized PCI config space. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Acked-by: Alex Williamson <alex.williamson@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/virtual/kvm/api.txt41
-rw-r--r--arch/x86/kvm/x86.c1
-rw-r--r--include/linux/kvm.h6
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--virt/kvm/assigned-dev.c209
5 files changed, 230 insertions, 29 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 59a38264a0ed..6386f8c0482e 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1169,6 +1169,14 @@ following flags are specified:
1169 1169
1170/* Depends on KVM_CAP_IOMMU */ 1170/* Depends on KVM_CAP_IOMMU */
1171#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) 1171#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
1172/* The following two depend on KVM_CAP_PCI_2_3 */
1173#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
1174#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
1175
1176If KVM_DEV_ASSIGN_PCI_2_3 is set, the kernel will manage legacy INTx interrupts
1177via the PCI-2.3-compliant device-level mask, thus enable IRQ sharing with other
1178assigned devices or host devices. KVM_DEV_ASSIGN_MASK_INTX specifies the
1179guest's view on the INTx mask, see KVM_ASSIGN_SET_INTX_MASK for details.
1172 1180
1173The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure 1181The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure
1174isolation of the device. Usages not specifying this flag are deprecated. 1182isolation of the device. Usages not specifying this flag are deprecated.
@@ -1441,6 +1449,39 @@ The "num_dirty" field is a performance hint for KVM to determine whether it
1441should skip processing the bitmap and just invalidate everything. It must 1449should skip processing the bitmap and just invalidate everything. It must
1442be set to the number of set bits in the bitmap. 1450be set to the number of set bits in the bitmap.
1443 1451
14524.60 KVM_ASSIGN_SET_INTX_MASK
1453
1454Capability: KVM_CAP_PCI_2_3
1455Architectures: x86
1456Type: vm ioctl
1457Parameters: struct kvm_assigned_pci_dev (in)
1458Returns: 0 on success, -1 on error
1459
1460Allows userspace to mask PCI INTx interrupts from the assigned device. The
1461kernel will not deliver INTx interrupts to the guest between setting and
1462clearing of KVM_ASSIGN_SET_INTX_MASK via this interface. This enables use of
1463and emulation of PCI 2.3 INTx disable command register behavior.
1464
1465This may be used for both PCI 2.3 devices supporting INTx disable natively and
1466older devices lacking this support. Userspace is responsible for emulating the
1467read value of the INTx disable bit in the guest visible PCI command register.
1468When modifying the INTx disable state, userspace should precede updating the
1469physical device command register by calling this ioctl to inform the kernel of
1470the new intended INTx mask state.
1471
1472Note that the kernel uses the device INTx disable bit to internally manage the
1473device interrupt state for PCI 2.3 devices. Reads of this register may
1474therefore not match the expected value. Writes should always use the guest
1475intended INTx disable value rather than attempting to read-copy-update the
1476current physical device state. Races between user and kernel updates to the
1477INTx disable bit are handled lazily in the kernel. It's possible the device
1478may generate unintended interrupts, but they will not be injected into the
1479guest.
1480
1481See KVM_ASSIGN_DEV_IRQ for the data structure. The target device is specified
1482by assigned_dev_id. In the flags field, only KVM_DEV_ASSIGN_MASK_INTX is
1483evaluated.
1484
14444.62 KVM_CREATE_SPAPR_TCE 14854.62 KVM_CREATE_SPAPR_TCE
1445 1486
1446Capability: KVM_CAP_SPAPR_TCE 1487Capability: KVM_CAP_SPAPR_TCE
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9477dc6cccae..6866083a48c1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2143,6 +2143,7 @@ int kvm_dev_ioctl_check_extension(long ext)
2143 case KVM_CAP_XSAVE: 2143 case KVM_CAP_XSAVE:
2144 case KVM_CAP_ASYNC_PF: 2144 case KVM_CAP_ASYNC_PF:
2145 case KVM_CAP_GET_TSC_KHZ: 2145 case KVM_CAP_GET_TSC_KHZ:
2146 case KVM_CAP_PCI_2_3:
2146 r = 1; 2147 r = 1;
2147 break; 2148 break;
2148 case KVM_CAP_COALESCED_MMIO: 2149 case KVM_CAP_COALESCED_MMIO:
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index acbe42939089..6c322a90b92f 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -588,6 +588,7 @@ struct kvm_ppc_pvinfo {
588#define KVM_CAP_TSC_DEADLINE_TIMER 72 588#define KVM_CAP_TSC_DEADLINE_TIMER 72
589#define KVM_CAP_S390_UCONTROL 73 589#define KVM_CAP_S390_UCONTROL 73
590#define KVM_CAP_SYNC_REGS 74 590#define KVM_CAP_SYNC_REGS 74
591#define KVM_CAP_PCI_2_3 75
591 592
592#ifdef KVM_CAP_IRQ_ROUTING 593#ifdef KVM_CAP_IRQ_ROUTING
593 594
@@ -784,6 +785,9 @@ struct kvm_s390_ucas_mapping {
784/* Available with KVM_CAP_TSC_CONTROL */ 785/* Available with KVM_CAP_TSC_CONTROL */
785#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2) 786#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2)
786#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3) 787#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3)
788/* Available with KVM_CAP_PCI_2_3 */
789#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \
790 struct kvm_assigned_pci_dev)
787 791
788/* 792/*
789 * ioctls for vcpu fds 793 * ioctls for vcpu fds
@@ -857,6 +861,8 @@ struct kvm_s390_ucas_mapping {
857#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg) 861#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
858 862
859#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) 863#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
864#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
865#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
860 866
861struct kvm_assigned_pci_dev { 867struct kvm_assigned_pci_dev {
862 __u32 assigned_dev_id; 868 __u32 assigned_dev_id;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index e42d85ae8541..ec171c1d0878 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -546,6 +546,7 @@ struct kvm_assigned_dev_kernel {
546 unsigned int entries_nr; 546 unsigned int entries_nr;
547 int host_irq; 547 int host_irq;
548 bool host_irq_disabled; 548 bool host_irq_disabled;
549 bool pci_2_3;
549 struct msix_entry *host_msix_entries; 550 struct msix_entry *host_msix_entries;
550 int guest_irq; 551 int guest_irq;
551 struct msix_entry *guest_msix_entries; 552 struct msix_entry *guest_msix_entries;
@@ -555,6 +556,7 @@ struct kvm_assigned_dev_kernel {
555 struct pci_dev *dev; 556 struct pci_dev *dev;
556 struct kvm *kvm; 557 struct kvm *kvm;
557 spinlock_t intx_lock; 558 spinlock_t intx_lock;
559 struct mutex intx_mask_lock;
558 char irq_name[32]; 560 char irq_name[32];
559 struct pci_saved_state *pci_saved_state; 561 struct pci_saved_state *pci_saved_state;
560}; 562};
diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
index ece80612b594..08e05715df72 100644
--- a/virt/kvm/assigned-dev.c
+++ b/virt/kvm/assigned-dev.c
@@ -55,22 +55,66 @@ static int find_index_from_host_irq(struct kvm_assigned_dev_kernel
55 return index; 55 return index;
56} 56}
57 57
58static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id) 58static irqreturn_t kvm_assigned_dev_intx(int irq, void *dev_id)
59{ 59{
60 struct kvm_assigned_dev_kernel *assigned_dev = dev_id; 60 struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
61 int ret;
61 62
62 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_INTX) { 63 spin_lock(&assigned_dev->intx_lock);
63 spin_lock(&assigned_dev->intx_lock); 64 if (pci_check_and_mask_intx(assigned_dev->dev)) {
65 assigned_dev->host_irq_disabled = true;
66 ret = IRQ_WAKE_THREAD;
67 } else
68 ret = IRQ_NONE;
69 spin_unlock(&assigned_dev->intx_lock);
70
71 return ret;
72}
73
74static void
75kvm_assigned_dev_raise_guest_irq(struct kvm_assigned_dev_kernel *assigned_dev,
76 int vector)
77{
78 if (unlikely(assigned_dev->irq_requested_type &
79 KVM_DEV_IRQ_GUEST_INTX)) {
80 mutex_lock(&assigned_dev->intx_mask_lock);
81 if (!(assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX))
82 kvm_set_irq(assigned_dev->kvm,
83 assigned_dev->irq_source_id, vector, 1);
84 mutex_unlock(&assigned_dev->intx_mask_lock);
85 } else
86 kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
87 vector, 1);
88}
89
90static irqreturn_t kvm_assigned_dev_thread_intx(int irq, void *dev_id)
91{
92 struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
93
94 if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
95 spin_lock_irq(&assigned_dev->intx_lock);
64 disable_irq_nosync(irq); 96 disable_irq_nosync(irq);
65 assigned_dev->host_irq_disabled = true; 97 assigned_dev->host_irq_disabled = true;
66 spin_unlock(&assigned_dev->intx_lock); 98 spin_unlock_irq(&assigned_dev->intx_lock);
67 } 99 }
68 100
69 kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id, 101 kvm_assigned_dev_raise_guest_irq(assigned_dev,
70 assigned_dev->guest_irq, 1); 102 assigned_dev->guest_irq);
103
104 return IRQ_HANDLED;
105}
106
107