diff options
| -rw-r--r-- | Documentation/virtual/kvm/api.txt | 41 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 1 | ||||
| -rw-r--r-- | include/linux/kvm.h | 6 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 2 | ||||
| -rw-r--r-- | virt/kvm/assigned-dev.c | 209 |
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 | |||
| 1176 | If KVM_DEV_ASSIGN_PCI_2_3 is set, the kernel will manage legacy INTx interrupts | ||
| 1177 | via the PCI-2.3-compliant device-level mask, thus enable IRQ sharing with other | ||
| 1178 | assigned devices or host devices. KVM_DEV_ASSIGN_MASK_INTX specifies the | ||
| 1179 | guest's view on the INTx mask, see KVM_ASSIGN_SET_INTX_MASK for details. | ||
| 1172 | 1180 | ||
| 1173 | The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure | 1181 | The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure |
| 1174 | isolation of the device. Usages not specifying this flag are deprecated. | 1182 | isolation 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 | |||
| 1441 | should skip processing the bitmap and just invalidate everything. It must | 1449 | should skip processing the bitmap and just invalidate everything. It must |
| 1442 | be set to the number of set bits in the bitmap. | 1450 | be set to the number of set bits in the bitmap. |
| 1443 | 1451 | ||
| 1452 | 4.60 KVM_ASSIGN_SET_INTX_MASK | ||
| 1453 | |||
| 1454 | Capability: KVM_CAP_PCI_2_3 | ||
| 1455 | Architectures: x86 | ||
| 1456 | Type: vm ioctl | ||
| 1457 | Parameters: struct kvm_assigned_pci_dev (in) | ||
| 1458 | Returns: 0 on success, -1 on error | ||
| 1459 | |||
| 1460 | Allows userspace to mask PCI INTx interrupts from the assigned device. The | ||
| 1461 | kernel will not deliver INTx interrupts to the guest between setting and | ||
| 1462 | clearing of KVM_ASSIGN_SET_INTX_MASK via this interface. This enables use of | ||
| 1463 | and emulation of PCI 2.3 INTx disable command register behavior. | ||
| 1464 | |||
| 1465 | This may be used for both PCI 2.3 devices supporting INTx disable natively and | ||
| 1466 | older devices lacking this support. Userspace is responsible for emulating the | ||
| 1467 | read value of the INTx disable bit in the guest visible PCI command register. | ||
| 1468 | When modifying the INTx disable state, userspace should precede updating the | ||
| 1469 | physical device command register by calling this ioctl to inform the kernel of | ||
| 1470 | the new intended INTx mask state. | ||
| 1471 | |||
| 1472 | Note that the kernel uses the device INTx disable bit to internally manage the | ||
| 1473 | device interrupt state for PCI 2.3 devices. Reads of this register may | ||
| 1474 | therefore not match the expected value. Writes should always use the guest | ||
| 1475 | intended INTx disable value rather than attempting to read-copy-update the | ||
| 1476 | current physical device state. Races between user and kernel updates to the | ||
| 1477 | INTx disable bit are handled lazily in the kernel. It's possible the device | ||
| 1478 | may generate unintended interrupts, but they will not be injected into the | ||
| 1479 | guest. | ||
| 1480 | |||
| 1481 | See KVM_ASSIGN_DEV_IRQ for the data structure. The target device is specified | ||
| 1482 | by assigned_dev_id. In the flags field, only KVM_DEV_ASSIGN_MASK_INTX is | ||
| 1483 | evaluated. | ||
| 1484 | |||
| 1444 | 4.62 KVM_CREATE_SPAPR_TCE | 1485 | 4.62 KVM_CREATE_SPAPR_TCE |
| 1445 | 1486 | ||
| 1446 | Capability: KVM_CAP_SPAPR_TCE | 1487 | Capability: 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 | ||
| 861 | struct kvm_assigned_pci_dev { | 867 | struct 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 | ||
| 58 | static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id) | 58 | static 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 | |||
| 74 | static void | ||
| 75 | kvm_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 | |||
| 90 | static 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 | #ifdef __KVM_HAVE_MSI | ||
| 108 | static irqreturn_t kvm_assigned_dev_thread_msi(int irq, void *dev_id) | ||
| 109 | { | ||
| 110 | struct kvm_assigned_dev_kernel *assigned_dev = dev_id; | ||
| 111 | |||
| 112 | kvm_assigned_dev_raise_guest_irq(assigned_dev, | ||
| 113 | assigned_dev->guest_irq); | ||
| 71 | |||
