From: Sheng Yang <sheng@linux.intel.com>
To: Avi Kivity <avi@redhat.com>, Anthony Liguori <anthony@codemonkey.ws>
Cc: kvm@vger.kernel.org, Sheng Yang <sheng@linux.intel.com>
Subject: [PATCH 3/3] Add MSI-X capability support
Date: Tue, 23 Dec 2008 16:32:37 +0800 [thread overview]
Message-ID: <1230021157-17327-4-git-send-email-sheng@linux.intel.com> (raw)
In-Reply-To: <1230021157-17327-1-git-send-email-sheng@linux.intel.com>
Expose MSI-X capabilty to guest if the assigned device got it.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
qemu/hw/device-assignment.c | 82 +++++++++++++++++++++++++++++++++++++++++--
qemu/hw/device-assignment.h | 3 ++
2 files changed, 82 insertions(+), 3 deletions(-)
diff --git a/qemu/hw/device-assignment.c b/qemu/hw/device-assignment.c
index 61d3f66..2d0c8a5 100644
--- a/qemu/hw/device-assignment.c
+++ b/qemu/hw/device-assignment.c
@@ -570,7 +570,9 @@ void assigned_dev_update_irq(PCIDevice *d)
}
}
-#if defined(KVM_CAP_DEVICE_MSI) && defined (KVM_CAP_GSI_MSG)
+#ifdef KVM_CAP_GSI_MSG
+
+#ifdef KVM_CAP_DEVICE_MSI
static void assigned_dev_update_msi(PCIDevice *pci_dev, unsigned int ctrl_pos)
{
struct kvm_assigned_irq assigned_irq_data;
@@ -610,6 +612,45 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev, unsigned int ctrl_pos)
}
#endif
+#ifdef KVM_CAP_DEVICE_MSIX
+static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos)
+{
+ struct kvm_assigned_irq assigned_irq_data;
+ AssignedDevice *assigned_dev = container_of(pci_dev, AssignedDevice, dev);
+ uint16_t *ctrl_word = (uint16_t *)(pci_dev->cap.config + ctrl_pos);
+
+ memset(&assigned_irq_data, 0, sizeof assigned_irq_data);
+ assigned_irq_data.assigned_dev_id =
+ calc_assigned_dev_id(assigned_dev->h_busnr,
+ (uint8_t)assigned_dev->h_devfn);
+
+ assigned_irq_data.flags = KVM_DEV_IRQ_ASSIGN_MSIX_ACTION;
+ if (*ctrl_word & PCI_MSIX_ENABLE)
+ assigned_irq_data.flags |= KVM_DEV_IRQ_ASSIGN_ENABLE_MSIX;
+ if (*ctrl_word & PCI_MSIX_MASK)
+ assigned_irq_data.flags |= KVM_DEV_IRQ_ASSIGN_MASK_MSIX;
+
+ if (kvm_assign_irq(kvm_context, &assigned_irq_data) < 0)
+ perror("assigned_dev_enable_msi");
+
+ if (assigned_irq_data.flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSIX) {
+ assigned_dev->cap.state |= ASSIGNED_DEVICE_MSIX_ENABLED;
+ *ctrl_word |= PCI_MSIX_ENABLE;
+ } else {
+ assigned_dev->cap.state &= ~ASSIGNED_DEVICE_MSIX_ENABLED;
+ *ctrl_word &= ~PCI_MSIX_ENABLE;
+ }
+ if (assigned_irq_data.flags & KVM_DEV_IRQ_ASSIGN_MASK_MSIX) {
+ assigned_dev->cap.state |= ASSIGNED_DEVICE_MSIX_MASKED;
+ *ctrl_word |= PCI_MSIX_MASK;
+ } else {
+ assigned_dev->cap.state &= ~ASSIGNED_DEVICE_MSIX_MASKED;
+ *ctrl_word &= ~PCI_MSIX_MASK;
+ }
+}
+#endif
+#endif
+
void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t address,
uint32_t val, int len)
{
@@ -617,7 +658,8 @@ void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t address,
unsigned int pos = pci_dev->cap.start, ctrl_pos;
pci_default_cap_write_config(pci_dev, address, val, len);
-#if defined(KVM_CAP_DEVICE_MSI) && defined (KVM_CAP_GSI_MSG)
+#ifdef KVM_CAP_GSI_MSG
+#ifdef KVM_CAP_DEVICE_MSI
if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
ctrl_pos = pos + PCI_MSI_FLAGS;
if (address <= ctrl_pos && address + len > ctrl_pos)
@@ -625,6 +667,17 @@ void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t address,
pos += PCI_CAPABILITY_CONFIG_MSI_LENGTH;
}
#endif
+#ifdef KVM_CAP_DEVICE_MSIX
+ if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
+ ctrl_pos = pos + 3;
+ if (address <= ctrl_pos && address + len > ctrl_pos) {
+ ctrl_pos--; /* control is word long */
+ assigned_dev_update_msix(pci_dev, ctrl_pos - pci_dev->cap.start);
+ }
+ pos += PCI_CAPABILITY_CONFIG_MSIX_LENGTH;
+ }
+#endif
+#endif
return;
}
@@ -643,7 +696,8 @@ void assigned_device_pci_cap_init(PCIDevice *pci_dev)
pci_init(pacc);
dev->pdev = pci_get_dev(pacc, 0, h_bus, h_dev, h_func);
pci_cleanup(pacc);
-#if defined(KVM_CAP_DEVICE_MSI) && defined (KVM_CAP_GSI_MSG)
+#ifdef KVM_CAP_GSI_MSG
+#ifdef KVM_CAP_DEVICE_MSI
/* Expose MSI capability
* MSI capability is the 1st capability in cap.config */
if (pci_find_cap_offset(dev->pdev, PCI_CAP_ID_MSI)) {
@@ -653,6 +707,28 @@ void assigned_device_pci_cap_init(PCIDevice *pci_dev)
next_cap_pt = 1;
}
#endif
+#ifdef KVM_CAP_DEVICE_MSIX
+ /* Expose MSI-X capability */
+ if (pci_find_cap_offset(dev->pdev, PCI_CAP_ID_MSIX)) {
+ int pos, entry_nr;
+ dev->cap.available |= ASSIGNED_DEVICE_CAP_MSIX;
+ pos = pci_find_cap_offset(dev->pdev, PCI_CAP_ID_MSIX);
+ entry_nr = pci_read_word(dev->pdev, pos + 2) & PCI_MSIX_TABSIZE;
+ pci_dev->cap.config[pci_dev->cap.length] = 0x11;
+ pci_dev->cap.config[pci_dev->cap.length + 2] = entry_nr;
+ *(uint32_t *)(pci_dev->cap.config +
+ pci_dev->cap.length + PCI_MSIX_TABLE) =
+ pci_read_long(dev->pdev, pos + PCI_MSIX_TABLE);
+ *(uint32_t *)(pci_dev->cap.config +
+ pci_dev->cap.length + PCI_MSIX_PBA) =
+ pci_read_long(dev->pdev, pos + PCI_MSIX_PBA);
+ pci_dev->cap.config[next_cap_pt] =
+ pci_dev->cap.start + pci_dev->cap.length;
+ pci_dev->cap.length += PCI_CAPABILITY_CONFIG_MSIX_LENGTH;
+ next_cap_pt += PCI_CAPABILITY_CONFIG_MSIX_LENGTH;
+ }
+#endif
+#endif
}
struct PCIDevice *init_assigned_device(AssignedDevInfo *adev, PCIBus *bus)
diff --git a/qemu/hw/device-assignment.h b/qemu/hw/device-assignment.h
index ea26de5..9348e2c 100644
--- a/qemu/hw/device-assignment.h
+++ b/qemu/hw/device-assignment.h
@@ -84,8 +84,11 @@ typedef struct {
struct pci_dev *pdev;
struct {
#define ASSIGNED_DEVICE_CAP_MSI (1 << 0)
+#define ASSIGNED_DEVICE_CAP_MSIX (1 << 1)
uint32_t available;
#define ASSIGNED_DEVICE_MSI_ENABLED (1 << 0)
+#define ASSIGNED_DEVICE_MSIX_ENABLED (1 << 1)
+#define ASSIGNED_DEVICE_MSIX_MASKED (1 << 2)
uint32_t state;
} cap;
} AssignedDevice;
--
1.5.4.5
prev parent reply other threads:[~2008-12-23 8:32 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-23 8:32 [PATCH 0/3] Userspace for MSI-X Sheng Yang
2008-12-23 8:32 ` [PATCH 1/3] Add MSI-X related macro to pci.c Sheng Yang
2008-12-23 8:32 ` [PATCH 2/3] KVM: Makefile change for intercepted MMIO Sheng Yang
2008-12-23 8:32 ` Sheng Yang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1230021157-17327-4-git-send-email-sheng@linux.intel.com \
--to=sheng@linux.intel.com \
--cc=anthony@codemonkey.ws \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.