From: Sheng Yang <sheng@linux.intel.com>
To: Avi Kivity <avi@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm@vger.kernel.org, Sheng Yang <sheng@linux.intel.com>
Subject: [PATCH 3/3] qemu-kvm: device assignment: emulate MSI-X mask bits
Date: Tue, 28 Sep 2010 17:44:12 +0800 [thread overview]
Message-ID: <1285667052-24907-4-git-send-email-sheng@linux.intel.com> (raw)
In-Reply-To: <1285667052-24907-1-git-send-email-sheng@linux.intel.com>
This patch emulated MSI-X per vector mask bit on assigned device.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
hw/device-assignment.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 126 insertions(+), 1 deletions(-)
diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 4edae52..564c5ab 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -1146,6 +1146,7 @@ static int get_msix_entries_max_nr(AssignedDevice *adev)
return entries_max_nr;
}
+#define MSIX_VECTOR_MASK 0x1
static int get_msix_valid_entries_nr(AssignedDevice *adev,
uint16_t entries_max_nr)
{
@@ -1159,7 +1160,11 @@ static int get_msix_valid_entries_nr(AssignedDevice *adev,
memcpy(&msg_ctrl, va + i * 16 + 12, 4);
memcpy(&msg_data, va + i * 16 + 8, 4);
/* Ignore unused entry even it's unmasked */
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+ if (msg_data == 0 || (msg_ctrl & MSIX_VECTOR_MASK))
+#else
if (msg_data == 0)
+#endif
continue;
entries_nr ++;
}
@@ -1188,6 +1193,8 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev,
}
free_dev_irq_entries(adev);
+ memset(pci_dev->msix_entry_used, 0, KVM_MAX_MSIX_PER_DEV *
+ sizeof(*pci_dev->msix_entry_used));
adev->irq_entries_nr = entries_nr;
adev->entry = calloc(entries_nr, sizeof(struct kvm_irq_routing_entry));
if (!adev->entry) {
@@ -1223,6 +1230,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev,
msix_entry.gsi = adev->entry[entries_nr].gsi;
msix_entry.entry = i;
+ pci_dev->msix_entry_used[i] = 1;
r = kvm_assign_set_msix_entry(kvm_context, &msix_entry);
if (r) {
fprintf(stderr, "fail to set MSI-X entry! %s\n", strerror(-r));
@@ -1266,6 +1274,8 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, int enable_msix)
perror("assigned_dev_update_msix: deassign irq");
assigned_dev->irq_requested_type = 0;
+ memset(pci_dev->msix_entry_used, 0, KVM_MAX_MSIX_PER_DEV *
+ sizeof(*pci_dev->msix_entry_used));
}
entries_max_nr = get_msix_entries_max_nr(assigned_dev);
@@ -1273,10 +1283,16 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, int enable_msix)
fprintf(stderr, "assigned_dev_update_msix: MSI-X entries_max_nr == 0");
return;
}
+ /*
+ * Guest may try to enable MSI-X before setting MSI-X entry done, so
+ * let's wait until guest unmask the entries.
+ */
entries_nr = get_msix_valid_entries_nr(assigned_dev, entries_max_nr);
if (entries_nr == 0) {
+#ifndef KVM_CAP_DEVICE_MSIX_MASK
if (enable_msix)
fprintf(stderr, "MSI-X entry number is zero!\n");
+#endif
return;
}
if (enable_msix) {
@@ -1320,7 +1336,8 @@ static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t ad
if (address <= ctrl_pos && address + len > ctrl_pos) {
ctrl_pos--; /* control is word long */
ctrl_word = (uint16_t *)(pci_dev->config + ctrl_pos);
- assigned_dev_update_msix(pci_dev, (*ctrl_word & PCI_MSIX_ENABLE));
+ assigned_dev_update_msix(pci_dev,
+ (*ctrl_word & PCI_MSIX_ENABLE) && !(*ctrl_word & PCI_MSIX_MASK));
}
pos += PCI_CAPABILITY_CONFIG_MSIX_LENGTH;
}
@@ -1412,6 +1429,104 @@ static uint32_t msix_mmio_readw(void *opaque, target_phys_addr_t addr)
(8 * (addr & 3))) & 0xffff;
}
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+static void msix_mmio_access_mask_bit(AssignedDevice *adev, int index)
+{
+ void *page = adev->msix_table_page;
+ uint32_t msg_ctrl, msg_data, msg_upper_addr, msg_addr;
+ struct kvm_assigned_msix_entry msix_entry;
+ int r = 0, pos, ctrl_word, entry_idx, entries_max_nr;
+ struct kvm_irq_routing_entry old_entry = {};
+
+ memcpy(&msg_addr, (char *)page + index * 16, 4);
+ memcpy(&msg_upper_addr, (char *)page + index * 16 + 4, 4);
+ memcpy(&msg_data, (char *)page + index * 16 + 8, 4);
+ memcpy(&msg_ctrl, (char *)page + index * 16 + 12, 4);
+ DEBUG("Access mask bit: MSI-X entries index %d: "
+ "msg_addr 0x%x, msg_upper_addr 0x%x, msg_data 0x%x, vec_ctl 0x%x\n",
+ index, msg_addr, msg_upper_addr, msg_data, msg_ctrl);
+
+ if (adev->cap.available & ASSIGNED_DEVICE_CAP_MSI)
+ pos = adev->dev.cap.start + PCI_CAPABILITY_CONFIG_MSI_LENGTH;
+ else
+ pos = adev->dev.cap.start;
+
+ ctrl_word = *(uint16_t *)(adev->dev.config + pos + 2);
+
+ if (!((ctrl_word & PCI_MSIX_ENABLE) && !(ctrl_word & PCI_MSIX_MASK)))
+ return;
+
+ if (!adev->dev.msix_entry_used[index] && (msg_ctrl & MSIX_VECTOR_MASK) == 0) {
+ DEBUG("Try to modify unenabled MSI-X entry %d's mask. "
+ "Reenable MSI-X.\n",
+ index);
+ assigned_dev_update_msix(&adev->dev, 1);
+ return;
+ }
+
+ /* find the correlated index of adev->entry */
+ entries_max_nr = get_msix_entries_max_nr(adev);
+ entry_idx = 0;
+ while (entry_idx < entries_max_nr)
+ if (adev->dev.msix_entry_used[index]) {
+ if (entry_idx == index)
+ break;
+ entry_idx ++;
+ }
+ if (entry_idx >= entries_max_nr) {
+ fprintf(stderr, "msix_mmio_access_mask_bit: Entry idx exceed limit!\n");
+ return;
+ }
+
+ msix_entry.assigned_dev_id = calc_assigned_dev_id(adev->h_segnr,
+ adev->h_busnr,
+ (uint8_t)adev->h_devfn);
+ msix_entry.gsi = adev->entry[entry_idx].gsi;
+ msix_entry.entry = index;
+ if (msg_ctrl & MSIX_VECTOR_MASK)
+ msix_entry.flags = KVM_MSIX_FLAG_MASK;
+ else
+ msix_entry.flags = 0;
+ DEBUG("set MSI-X index %d, esi 0x%x, mask %d\n",
+ index, msix_entry.gsi, msix_entry.flags);
+ r = kvm_assign_set_msix_entry(kvm_context, &msix_entry);
+ if (r) {
+ perror("msix_mmio_access_mask_bit: "
+ "fail to set MSI-X entry!");
+ return;
+ }
+
+ if (msix_entry.flags == 0) {
+ old_entry.gsi = adev->entry[entry_idx].gsi;
+ old_entry.type = KVM_IRQ_ROUTING_MSI;
+ old_entry.flags = 0;
+ old_entry.u.msi.address_lo = adev->entry[entry_idx].u.msi.address_lo;
+ old_entry.u.msi.address_hi = adev->entry[entry_idx].u.msi.address_hi;
+ old_entry.u.msi.data = adev->entry[entry_idx].u.msi.data;
+ adev->entry[entry_idx].u.msi.address_lo = msg_addr;
+ adev->entry[entry_idx].u.msi.address_hi = msg_upper_addr;
+ adev->entry[entry_idx].u.msi.data = msg_data;
+ if (memcmp(&adev->entry[entry_idx].u.msi, &old_entry.u.msi,
+ sizeof old_entry.u.msi)) {
+ int r;
+ r = kvm_update_routing_entry(kvm_context, &old_entry,
+ &adev->entry[entry_idx]);
+ if (r) {
+ perror("msix_mmio_access_mask_bit: "
+ "kvm_update_routing_entry failed\n");
+ return;
+ }
+ r = kvm_commit_irq_routes(kvm_context);
+ if (r) {
+ perror("msix_mmio_access_mask_bit: "
+ "kvm_commit_irq_routes failed\n");
+ return;
+ }
+ }
+ }
+}
+#endif
+
static void msix_mmio_writel(void *opaque,
target_phys_addr_t addr, uint32_t val)
{
@@ -1422,6 +1537,12 @@ static void msix_mmio_writel(void *opaque,
DEBUG("write to MSI-X entry table mmio offset 0x%lx, val 0x%x\n",
addr, val);
memcpy((void *)((char *)page + offset), &val, 4);
+
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+ /* Check if mask bit is being accessed */
+ if (offset % 16 == 12)
+ msix_mmio_access_mask_bit(adev, offset / 16);
+#endif
}
static void msix_mmio_writew(void *opaque,
@@ -1459,6 +1580,8 @@ static int assigned_dev_register_msix_mmio(AssignedDevice *dev)
memset(dev->msix_table_page, 0, 0x1000);
dev->mmio_index = cpu_register_io_memory(
msix_mmio_read, msix_mmio_write, dev);
+ dev->dev.msix_entry_used = qemu_mallocz(KVM_MAX_MSIX_PER_DEV *
+ sizeof *dev->dev.msix_entry_used);
return 0;
}
@@ -1475,6 +1598,8 @@ static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev)
strerror(errno));
}
dev->msix_table_page = NULL;
+ free(dev->dev.msix_entry_used);
+ dev->dev.msix_entry_used = NULL;
}
static int assigned_initfn(struct PCIDevice *pci_dev)
--
1.7.0.1
next prev parent reply other threads:[~2010-09-28 9:44 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-28 9:44 [PATCH 0/3] Emulate MSI-X mask bits for assigned devices Sheng Yang
2010-09-28 9:44 ` [PATCH 1/3] KVM: Emulation " Sheng Yang
2010-09-28 13:36 ` Michael S. Tsirkin
2010-09-29 1:17 ` Sheng Yang
2010-09-30 16:25 ` Marcelo Tosatti
2010-09-29 8:36 ` Avi Kivity
2010-09-30 5:41 ` Sheng Yang
2010-10-03 13:03 ` Avi Kivity
2010-10-11 9:32 ` Sheng Yang
2010-09-30 16:18 ` Marcelo Tosatti
2010-10-11 9:49 ` Sheng Yang
2010-10-11 17:11 ` Marcelo Tosatti
2010-10-03 11:12 ` Michael S. Tsirkin
2010-10-11 9:28 ` Sheng Yang
2010-10-11 10:01 ` Michael S. Tsirkin
2010-10-12 6:49 ` Sheng Yang
2010-10-12 18:28 ` Michael S. Tsirkin
2010-10-13 1:03 ` Sheng Yang
2010-10-13 10:35 ` Michael S. Tsirkin
2010-10-12 18:30 ` Michael S. Tsirkin
2010-10-13 0:58 ` Sheng Yang
2010-10-13 12:03 ` Michael S. Tsirkin
2010-09-28 9:44 ` [PATCH 2/3] qemu-kvm: device assignment: Some clean up for MSI-X code Sheng Yang
2010-09-28 9:44 ` Sheng Yang [this message]
2010-09-30 16:44 ` [PATCH 0/3] Emulate MSI-X mask bits for assigned devices Marcelo Tosatti
2010-10-11 9:34 ` Sheng Yang
-- strict thread matches above, loose matches on Subject: below --
2010-11-04 6:18 [PATCH 0/3] MSI-X mask supporting for assigned device(QEmu) Sheng Yang
2010-11-04 6:18 ` [PATCH 3/3] qemu-kvm: device assignment: emulate MSI-X mask bits Sheng Yang
2010-11-04 9:44 ` Michael S. Tsirkin
2010-11-05 3:20 ` Sheng Yang
2010-11-05 9:05 ` Michael S. Tsirkin
2010-11-05 11:02 ` Sheng Yang
2010-11-05 13:54 ` Michael S. Tsirkin
2010-11-08 5:17 ` Sheng Yang
2010-11-08 6:27 ` Michael S. Tsirkin
2010-11-04 10:04 ` Michael S. Tsirkin
2010-11-05 3:14 ` Sheng Yang
2010-11-05 8:59 ` Michael S. Tsirkin
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=1285667052-24907-4-git-send-email-sheng@linux.intel.com \
--to=sheng@linux.intel.com \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
/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.