* [PATCH 0/5] MSI-X mask support for assigned device on userspace
@ 2010-10-20 8:29 Sheng Yang
2010-10-20 8:29 ` [PATCH 1/5] qemu-kvm: Add kvm_enable_cap() interface for x86 Sheng Yang
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Sheng Yang @ 2010-10-20 8:29 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Michael S. Tsirkin, kvm, Sheng Yang
Sheng Yang (5):
qemu-kvm: Add kvm_enable_cap() interface for x86
qemu-kvm: Ioctl for in-kernel mask support
qemu-kvm: device assignment: Some clean up about MSI-X code
qemu-kvm: device assignment: emulate MSI-X mask bits
qemu-kvm: device assignment: Enable in-kernel MSI-X mask support
hw/device-assignment.c | 239 ++++++++++++++++++++++++++++++++++++++++++------
qemu-kvm.c | 25 +++++
qemu-kvm.h | 12 +++
3 files changed, 246 insertions(+), 30 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/5] qemu-kvm: Add kvm_enable_cap() interface for x86
2010-10-20 8:29 [PATCH 0/5] MSI-X mask support for assigned device on userspace Sheng Yang
@ 2010-10-20 8:29 ` Sheng Yang
2010-10-20 8:29 ` [PATCH 2/5] qemu-kvm: Ioctl for in-kernel mask support Sheng Yang
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2010-10-20 8:29 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Michael S. Tsirkin, kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
qemu-kvm.c | 16 ++++++++++++++++
qemu-kvm.h | 8 ++++++++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 733d0a9..fbb68f6 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -540,6 +540,22 @@ int kvm_set_xcrs(CPUState *env, struct kvm_xcrs *xcrs)
}
#endif
+#ifdef KVM_CAP_ENABLE_CAP
+int kvm_enable_cap(CPUState *env, uint32_t cap)
+{
+ int r = 0;
+ struct kvm_enable_cap enable_cap = {
+ .cap = cap,
+ .flags = 0,
+ };
+
+ r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_ENABLE_CAP);
+ if (r > 0)
+ r = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &enable_cap);
+ return r;
+}
+#endif
+
static int handle_mmio(CPUState *env)
{
unsigned long addr = env->kvm_run->mmio.phys_addr;
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 9c08ab4..5cac0c2 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -316,6 +316,14 @@ int kvm_get_xcrs(CPUState *env, struct kvm_xcrs *xcrs);
int kvm_set_xcrs(CPUState *env, struct kvm_xcrs *xcrs);
#endif
+#ifdef KVM_ENABLE_CAP
+/*!
+ * * \brief Enable specific capability of KVM
+ *
+ */
+int kvm_enable_cap(CPUState *env, uint32_t cap);
+#endif
+
/*!
* \brief Simulate an external vectored interrupt
*
--
1.7.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/5] qemu-kvm: Ioctl for in-kernel mask support
2010-10-20 8:29 [PATCH 0/5] MSI-X mask support for assigned device on userspace Sheng Yang
2010-10-20 8:29 ` [PATCH 1/5] qemu-kvm: Add kvm_enable_cap() interface for x86 Sheng Yang
@ 2010-10-20 8:29 ` Sheng Yang
2010-10-20 8:29 ` [PATCH 3/5] qemu-kvm: device assignment: Some clean up about MSI-X code Sheng Yang
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2010-10-20 8:29 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Michael S. Tsirkin, kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
qemu-kvm.c | 9 +++++++++
qemu-kvm.h | 4 ++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/qemu-kvm.c b/qemu-kvm.c
index fbb68f6..bb817d6 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -1108,6 +1108,15 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm,
{
return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_SET_MSIX_ENTRY, entry);
}
+
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+int kvm_assign_reg_msix_mmio(kvm_context_t kvm,
+ struct kvm_assigned_msix_mmio *msix_mmio)
+{
+ return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_REG_MSIX_MMIO, msix_mmio);
+}
+#endif
+
#endif
#if defined(KVM_CAP_IRQFD) && defined(CONFIG_EVENTFD)
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 5cac0c2..ff8ca00 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -751,6 +751,10 @@ int kvm_assign_set_msix_nr(kvm_context_t kvm,
struct kvm_assigned_msix_nr *msix_nr);
int kvm_assign_set_msix_entry(kvm_context_t kvm,
struct kvm_assigned_msix_entry *entry);
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+int kvm_assign_reg_msix_mmio(kvm_context_t kvm,
+ struct kvm_assigned_msix_mmio *msix_mmio);
+#endif
#endif
#else /* !CONFIG_KVM */
--
1.7.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/5] qemu-kvm: device assignment: Some clean up about MSI-X code
2010-10-20 8:29 [PATCH 0/5] MSI-X mask support for assigned device on userspace Sheng Yang
2010-10-20 8:29 ` [PATCH 1/5] qemu-kvm: Add kvm_enable_cap() interface for x86 Sheng Yang
2010-10-20 8:29 ` [PATCH 2/5] qemu-kvm: Ioctl for in-kernel mask support Sheng Yang
@ 2010-10-20 8:29 ` Sheng Yang
2010-10-20 8:29 ` [PATCH 4/5] qemu-kvm: device assignment: emulate MSI-X mask bits Sheng Yang
2010-10-20 8:29 ` [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support Sheng Yang
4 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2010-10-20 8:29 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Michael S. Tsirkin, kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
hw/device-assignment.c | 77 ++++++++++++++++++++++++++++++++---------------
1 files changed, 52 insertions(+), 25 deletions(-)
diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 2605bd1..8a98876 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -1106,15 +1106,10 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev, unsigned int ctrl_pos)
#endif
#ifdef KVM_CAP_DEVICE_MSIX
-static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
+static int get_msix_entries_max_nr(AssignedDevice *adev)
{
- AssignedDevice *adev = container_of(pci_dev, AssignedDevice, dev);
- uint16_t entries_nr = 0, entries_max_nr;
- int pos = 0, i, r = 0;
- uint32_t msg_addr, msg_upper_addr, msg_data, msg_ctrl;
- struct kvm_assigned_msix_nr msix_nr;
- struct kvm_assigned_msix_entry msix_entry;
- void *va = adev->msix_table_page;
+ int pos, entries_max_nr;
+ PCIDevice *pci_dev = &adev->dev;
if (adev->cap.available & ASSIGNED_DEVICE_CAP_MSI)
pos = pci_dev->cap.start + PCI_CAPABILITY_CONFIG_MSI_LENGTH;
@@ -1125,6 +1120,17 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
entries_max_nr &= PCI_MSIX_TABSIZE;
entries_max_nr += 1;
+ return entries_max_nr;
+}
+
+static int get_msix_valid_entries_nr(AssignedDevice *adev,
+ uint16_t entries_max_nr)
+{
+ void *va = adev->msix_table_page;
+ uint32_t msg_data, msg_ctrl;
+ uint16_t entries_nr = 0;
+ int i;
+
/* Get the usable entry number for allocating */
for (i = 0; i < entries_max_nr; i++) {
memcpy(&msg_ctrl, va + i * 16 + 12, 4);
@@ -1134,11 +1140,20 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
continue;
entries_nr ++;
}
+ return entries_nr;
+}
+
+static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev,
+ uint16_t entries_nr,
+ uint16_t entries_max_nr)
+{
+ AssignedDevice *adev = container_of(pci_dev, AssignedDevice, dev);
+ int i, r = 0;
+ uint32_t msg_addr, msg_upper_addr, msg_data, msg_ctrl;
+ struct kvm_assigned_msix_nr msix_nr;
+ struct kvm_assigned_msix_entry msix_entry;
+ void *va = adev->msix_table_page;
- if (entries_nr == 0) {
- fprintf(stderr, "MSI-X entry number is zero!\n");
- return -EINVAL;
- }
msix_nr.assigned_dev_id = calc_assigned_dev_id(adev->h_segnr, adev->h_busnr,
(uint8_t)adev->h_devfn);
msix_nr.entry_nr = entries_nr;
@@ -1180,8 +1195,8 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
adev->entry[entries_nr].u.msi.address_lo = msg_addr;
adev->entry[entries_nr].u.msi.address_hi = msg_upper_addr;
adev->entry[entries_nr].u.msi.data = msg_data;
- DEBUG("MSI-X data 0x%x, MSI-X addr_lo 0x%x\n!", msg_data, msg_addr);
- kvm_add_routing_entry(&adev->entry[entries_nr]);
+ DEBUG("MSI-X data 0x%x, MSI-X addr_lo 0x%x!\n", msg_data, msg_addr);
+ kvm_add_routing_entry(&adev->entry[entries_nr]);
msix_entry.gsi = adev->entry[entries_nr].gsi;
msix_entry.entry = i;
@@ -1190,7 +1205,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
fprintf(stderr, "fail to set MSI-X entry! %s\n", strerror(-r));
break;
}
- DEBUG("MSI-X entry gsi 0x%x, entry %d\n!",
+ DEBUG("MSI-X entry gsi 0x%x, entry %d!\n",
msix_entry.gsi, msix_entry.entry);
entries_nr ++;
}
@@ -1203,12 +1218,12 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
return r;
}
-static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos)
+static void assigned_dev_update_msix(PCIDevice *pci_dev, int enable_msix)
{
struct kvm_assigned_irq assigned_irq_data;
AssignedDevice *assigned_dev = container_of(pci_dev, AssignedDevice, dev);
- uint16_t *ctrl_word = (uint16_t *)(pci_dev->config + ctrl_pos);
int r;
+ uint16_t entries_nr, entries_max_nr;
memset(&assigned_irq_data, 0, sizeof assigned_irq_data);
assigned_irq_data.assigned_dev_id =
@@ -1219,8 +1234,7 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos)
* try to catch this by only deassigning irqs if the guest is using
* MSIX or intends to start. */
if ((assigned_dev->irq_requested_type & KVM_DEV_IRQ_GUEST_MSIX) ||
- (*ctrl_word & PCI_MSIX_ENABLE)) {
-
+ enable_msix) {
assigned_irq_data.flags = assigned_dev->irq_requested_type;
free_dev_irq_entries(assigned_dev);
r = kvm_deassign_irq(kvm_context, &assigned_irq_data);
@@ -1231,14 +1245,25 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos)
assigned_dev->irq_requested_type = 0;
}
- if (*ctrl_word & PCI_MSIX_ENABLE) {
- assigned_irq_data.flags = KVM_DEV_IRQ_HOST_MSIX |
- KVM_DEV_IRQ_GUEST_MSIX;
-
- if (assigned_dev_update_msix_mmio(pci_dev) < 0) {
+ entries_max_nr = get_msix_entries_max_nr(assigned_dev);
+ if (entries_max_nr == 0) {
+ fprintf(stderr, "assigned_dev_update_msix: MSI-X entries_max_nr == 0");
+ return;
+ }
+ entries_nr = get_msix_valid_entries_nr(assigned_dev, entries_max_nr);
+ if (entries_nr == 0) {
+ if (enable_msix)
+ fprintf(stderr, "MSI-X entry number is zero!\n");
+ return;
+ }
+ if (enable_msix) {
+ if (assigned_dev_update_msix_mmio(pci_dev,
+ entries_nr, entries_max_nr) < 0) {
perror("assigned_dev_update_msix_mmio");
return;
}
+ assigned_irq_data.flags = KVM_DEV_IRQ_HOST_MSIX |
+ KVM_DEV_IRQ_GUEST_MSIX;
if (kvm_assign_irq(kvm_context, &assigned_irq_data) < 0) {
perror("assigned_dev_enable_msix: assign irq");
return;
@@ -1254,6 +1279,7 @@ static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t ad
{
AssignedDevice *assigned_dev = container_of(pci_dev, AssignedDevice, dev);
unsigned int pos = pci_dev->cap.start, ctrl_pos;
+ uint16_t *ctrl_word;
pci_default_cap_write_config(pci_dev, address, val, len);
#ifdef KVM_CAP_IRQ_ROUTING
@@ -1270,7 +1296,8 @@ static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t ad
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);
+ ctrl_word = (uint16_t *)(pci_dev->config + ctrl_pos);
+ assigned_dev_update_msix(pci_dev, (*ctrl_word & PCI_MSIX_ENABLE));
}
pos += PCI_CAPABILITY_CONFIG_MSIX_LENGTH;
}
--
1.7.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/5] qemu-kvm: device assignment: emulate MSI-X mask bits
2010-10-20 8:29 [PATCH 0/5] MSI-X mask support for assigned device on userspace Sheng Yang
` (2 preceding siblings ...)
2010-10-20 8:29 ` [PATCH 3/5] qemu-kvm: device assignment: Some clean up about MSI-X code Sheng Yang
@ 2010-10-20 8:29 ` Sheng Yang
2010-10-20 8:29 ` [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support Sheng Yang
4 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2010-10-20 8:29 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Michael S. Tsirkin, kvm, Sheng Yang
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 | 151 ++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 145 insertions(+), 6 deletions(-)
diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 8a98876..d1a6282 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -62,6 +62,11 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev);
static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev);
+static uint32_t calc_assigned_dev_id(uint16_t seg, uint8_t bus, uint8_t devfn)
+{
+ return (uint32_t)seg << 16 | (uint32_t)bus << 8 | (uint32_t)devfn;
+}
+
static uint32_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region,
uint32_t addr, int len, uint32_t *val)
{
@@ -824,11 +829,6 @@ static void free_assigned_device(AssignedDevice *dev)
}
}
-static uint32_t calc_assigned_dev_id(uint16_t seg, uint8_t bus, uint8_t devfn)
-{
- return (uint32_t)seg << 16 | (uint32_t)bus << 8 | (uint32_t)devfn;
-}
-
static void assign_failed_examine(AssignedDevice *dev)
{
char name[PATH_MAX], dir[PATH_MAX], driver[PATH_MAX] = {}, *ns;
@@ -1123,6 +1123,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)
{
@@ -1136,7 +1137,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 ++;
}
@@ -1165,6 +1170,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) {
@@ -1179,7 +1186,11 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev,
break;
memcpy(&msg_ctrl, va + i * 16 + 12, 4);
memcpy(&msg_data, va + i * 16 + 8, 4);
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+ if (msg_data == 0 || (msg_ctrl & MSIX_VECTOR_MASK))
+#else
if (msg_data == 0)
+#endif
continue;
memcpy(&msg_addr, va + i * 16, 4);
@@ -1200,6 +1211,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));
@@ -1243,6 +1255,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);
@@ -1250,10 +1264,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) {
@@ -1297,7 +1317,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;
}
@@ -1389,6 +1410,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 new_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]) {
+ if ((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[entry_idx] && 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) {
+ new_entry.gsi = adev->entry[entry_idx].gsi;
+ new_entry.type = KVM_IRQ_ROUTING_MSI;
+ new_entry.flags = 0;
+ new_entry.u.msi.address_lo = msg_addr;
+ new_entry.u.msi.address_hi = msg_upper_addr;
+ new_entry.u.msi.data = msg_data;
+ if (memcmp(&adev->entry[entry_idx].u.msi, &new_entry.u.msi,
+ sizeof new_entry.u.msi)) {
+ int r;
+ r = kvm_update_routing_entry(&adev->entry[entry_idx], &new_entry);
+ if (r) {
+ perror("msix_mmio_access_mask_bit: "
+ "kvm_update_routing_entry failed\n");
+ return;
+ }
+ r = kvm_commit_irq_routes();
+ if (r) {
+ perror("msix_mmio_access_mask_bit: "
+ "kvm_commit_irq_routes failed\n");
+ return;
+ }
+ }
+ 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;
+ }
+}
+#endif
+
static void msix_mmio_writel(void *opaque,
target_phys_addr_t addr, uint32_t val)
{
@@ -1399,6 +1518,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,
@@ -1425,6 +1550,16 @@ static CPUReadMemoryFunc *msix_mmio_read[] = {
static int assigned_dev_register_msix_mmio(AssignedDevice *dev)
{
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+#ifndef KVM_CAP_DEVICE_MSIX_EXT
+#error
+#endif
+ /* Request for MSI-X masking support */
+ if (kvm_enable_cap(first_cpu, KVM_CAP_DEVICE_MSIX_EXT) != 0) {
+ fprintf(stderr, "fail to enable MSI-X extending support!\n");
+ return -EFAULT;
+ }
+#endif
dev->msix_table_page = mmap(NULL, 0x1000,
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
@@ -1436,6 +1571,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;
}
@@ -1452,6 +1589,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
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support
2010-10-20 8:29 [PATCH 0/5] MSI-X mask support for assigned device on userspace Sheng Yang
` (3 preceding siblings ...)
2010-10-20 8:29 ` [PATCH 4/5] qemu-kvm: device assignment: emulate MSI-X mask bits Sheng Yang
@ 2010-10-20 8:29 ` Sheng Yang
2010-10-20 22:36 ` Michael S. Tsirkin
4 siblings, 1 reply; 9+ messages in thread
From: Sheng Yang @ 2010-10-20 8:29 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Michael S. Tsirkin, kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
hw/device-assignment.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index d1a6282..aa3358e 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -269,6 +269,9 @@ static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num,
AssignedDevRegion *region = &r_dev->v_addrs[region_num];
PCIRegion *real_region = &r_dev->real_device.regions[region_num];
int ret = 0;
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+ struct kvm_assigned_msix_mmio msix_mmio;
+#endif
DEBUG("e_phys=%08" FMT_PCIBUS " r_virt=%p type=%d len=%08" FMT_PCIBUS " region_num=%d \n",
e_phys, region->u.r_virtbase, type, e_size, region_num);
@@ -287,6 +290,16 @@ static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(e_phys + offset,
TARGET_PAGE_SIZE, r_dev->mmio_index);
+#ifdef KVM_CAP_DEVICE_MSIX_MASK
+ memset(&msix_mmio, 0, sizeof(struct kvm_assigned_msix_mmio));
+ msix_mmio.assigned_dev_id = calc_assigned_dev_id(r_dev->h_segnr,
+ r_dev->h_busnr, r_dev->h_devfn);
+ msix_mmio.base_addr = e_phys + offset;
+ if (kvm_assign_reg_msix_mmio(kvm_context, &msix_mmio))
+ fprintf(stderr, "fail to register in-kernel msix_mmio!\n");
+ /* We can still continue because the MMIO accessing can fall
+ * back to QEmu */
+#endif
}
}
--
1.7.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support
2010-10-20 8:29 ` [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support Sheng Yang
@ 2010-10-20 22:36 ` Michael S. Tsirkin
2010-10-21 7:12 ` Sheng Yang
0 siblings, 1 reply; 9+ messages in thread
From: Michael S. Tsirkin @ 2010-10-20 22:36 UTC (permalink / raw)
To: Sheng Yang; +Cc: Avi Kivity, Marcelo Tosatti, kvm
On Wed, Oct 20, 2010 at 04:29:55PM +0800, Sheng Yang wrote:
>
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
> hw/device-assignment.c | 13 +++++++++++++
> 1 files changed, 13 insertions(+), 0 deletions(-)
>
> diff --git a/hw/device-assignment.c b/hw/device-assignment.c
> index d1a6282..aa3358e 100644
> --- a/hw/device-assignment.c
> +++ b/hw/device-assignment.c
> @@ -269,6 +269,9 @@ static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num,
> AssignedDevRegion *region = &r_dev->v_addrs[region_num];
> PCIRegion *real_region = &r_dev->real_device.regions[region_num];
> int ret = 0;
> +#ifdef KVM_CAP_DEVICE_MSIX_MASK
> + struct kvm_assigned_msix_mmio msix_mmio;
> +#endif
>
> DEBUG("e_phys=%08" FMT_PCIBUS " r_virt=%p type=%d len=%08" FMT_PCIBUS " region_num=%d \n",
> e_phys, region->u.r_virtbase, type, e_size, region_num);
> @@ -287,6 +290,16 @@ static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num,
>
> cpu_register_physical_memory(e_phys + offset,
> TARGET_PAGE_SIZE, r_dev->mmio_index);
> +#ifdef KVM_CAP_DEVICE_MSIX_MASK
> + memset(&msix_mmio, 0, sizeof(struct kvm_assigned_msix_mmio));
> + msix_mmio.assigned_dev_id = calc_assigned_dev_id(r_dev->h_segnr,
> + r_dev->h_busnr, r_dev->h_devfn);
> + msix_mmio.base_addr = e_phys + offset;
> + if (kvm_assign_reg_msix_mmio(kvm_context, &msix_mmio))
> + fprintf(stderr, "fail to register in-kernel msix_mmio!\n");
> + /* We can still continue because the MMIO accessing can fall
> + * back to QEmu */
So let's not print scary messages ...
> +#endif
> }
> }
>
> --
> 1.7.0.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support
2010-10-20 22:36 ` Michael S. Tsirkin
@ 2010-10-21 7:12 ` Sheng Yang
0 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2010-10-21 7:12 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Avi Kivity, Marcelo Tosatti, kvm
On Thursday 21 October 2010 06:36:56 Michael S. Tsirkin wrote:
> On Wed, Oct 20, 2010 at 04:29:55PM +0800, Sheng Yang wrote:
> > Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> > ---
> >
> > hw/device-assignment.c | 13 +++++++++++++
> > 1 files changed, 13 insertions(+), 0 deletions(-)
> >
> > diff --git a/hw/device-assignment.c b/hw/device-assignment.c
> > index d1a6282..aa3358e 100644
> > --- a/hw/device-assignment.c
> > +++ b/hw/device-assignment.c
> > @@ -269,6 +269,9 @@ static void assigned_dev_iomem_map(PCIDevice
> > *pci_dev, int region_num,
> >
> > AssignedDevRegion *region = &r_dev->v_addrs[region_num];
> > PCIRegion *real_region = &r_dev->real_device.regions[region_num];
> > int ret = 0;
> >
> > +#ifdef KVM_CAP_DEVICE_MSIX_MASK
> > + struct kvm_assigned_msix_mmio msix_mmio;
> > +#endif
> >
> > DEBUG("e_phys=%08" FMT_PCIBUS " r_virt=%p type=%d len=%08"
> > FMT_PCIBUS " region_num=%d \n",
> >
> > e_phys, region->u.r_virtbase, type, e_size, region_num);
> >
> > @@ -287,6 +290,16 @@ static void assigned_dev_iomem_map(PCIDevice
> > *pci_dev, int region_num,
> >
> > cpu_register_physical_memory(e_phys + offset,
> >
> > TARGET_PAGE_SIZE, r_dev->mmio_index);
> >
> > +#ifdef KVM_CAP_DEVICE_MSIX_MASK
> > + memset(&msix_mmio, 0, sizeof(struct kvm_assigned_msix_mmio));
> > + msix_mmio.assigned_dev_id = calc_assigned_dev_id(r_dev->h_segnr,
> > + r_dev->h_busnr, r_dev->h_devfn);
> > + msix_mmio.base_addr = e_phys + offset;
> > + if (kvm_assign_reg_msix_mmio(kvm_context, &msix_mmio))
> > + fprintf(stderr, "fail to register in-kernel
> > msix_mmio!\n"); + /* We can still continue because the MMIO
> > accessing can fall + * back to QEmu */
>
> So let's not print scary messages ...
OK...
--
regards
Yang, Sheng
>
> > +#endif
> >
> > }
> >
> > }
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/5] qemu-kvm: Ioctl for in-kernel mask support
2010-11-11 7:51 [PATCH 0/5 v4] MSI-X mask support for userspace Sheng Yang
@ 2010-11-11 7:51 ` Sheng Yang
0 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2010-11-11 7:51 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti, Michael S. Tsirkin; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
qemu-kvm.c | 14 ++++++++++++++
qemu-kvm.h | 7 +++++++
2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 733d0a9..aa30144 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -1094,6 +1094,20 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm,
}
#endif
+#ifdef KVM_CAP_MSIX_MASK
+int kvm_get_msix_entry(kvm_context_t kvm,
+ struct kvm_msix_entry *entry)
+{
+ return kvm_vm_ioctl(kvm_state, KVM_GET_MSIX_ENTRY, entry);
+}
+
+int kvm_update_msix_mmio(kvm_context_t kvm,
+ struct kvm_msix_mmio *msix_mmio)
+{
+ return kvm_vm_ioctl(kvm_state, KVM_UPDATE_MSIX_MMIO, msix_mmio);
+}
+#endif
+
#if defined(KVM_CAP_IRQFD) && defined(CONFIG_EVENTFD)
#include <sys/eventfd.h>
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 9c08ab4..d103140 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -745,6 +745,13 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm,
struct kvm_assigned_msix_entry *entry);
#endif
+#ifdef KVM_CAP_MSIX_MASK
+int kvm_get_msix_entry(kvm_context_t kvm,
+ struct kvm_msix_entry *entry);
+int kvm_update_msix_mmio(kvm_context_t kvm,
+ struct kvm_msix_mmio *msix_mmio);
+#endif
+
#else /* !CONFIG_KVM */
typedef struct kvm_context *kvm_context_t;
--
1.7.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-11-11 7:51 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-20 8:29 [PATCH 0/5] MSI-X mask support for assigned device on userspace Sheng Yang
2010-10-20 8:29 ` [PATCH 1/5] qemu-kvm: Add kvm_enable_cap() interface for x86 Sheng Yang
2010-10-20 8:29 ` [PATCH 2/5] qemu-kvm: Ioctl for in-kernel mask support Sheng Yang
2010-10-20 8:29 ` [PATCH 3/5] qemu-kvm: device assignment: Some clean up about MSI-X code Sheng Yang
2010-10-20 8:29 ` [PATCH 4/5] qemu-kvm: device assignment: emulate MSI-X mask bits Sheng Yang
2010-10-20 8:29 ` [PATCH 5/5] qemu-kvm: device assignment: Enable in-kernel MSI-X mask support Sheng Yang
2010-10-20 22:36 ` Michael S. Tsirkin
2010-10-21 7:12 ` Sheng Yang
-- strict thread matches above, loose matches on Subject: below --
2010-11-11 7:51 [PATCH 0/5 v4] MSI-X mask support for userspace Sheng Yang
2010-11-11 7:51 ` [PATCH 2/5] qemu-kvm: Ioctl for in-kernel mask support Sheng Yang
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.