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 4/4] Add MSI capability support
Date: Fri, 21 Nov 2008 17:04:27 +0800 [thread overview]
Message-ID: <1227258267-22901-5-git-send-email-sheng@linux.intel.com> (raw)
In-Reply-To: <1227258267-22901-1-git-send-email-sheng@linux.intel.com>
Now QEmu emulate a configuration space of capability region, and provide MSI
capability here.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
qemu/hw/device-assignment.c | 61 +++++++++++++++++++++++++++++++++++++++---
qemu/hw/device-assignment.h | 3 ++
2 files changed, 59 insertions(+), 5 deletions(-)
diff --git a/qemu/hw/device-assignment.c b/qemu/hw/device-assignment.c
index 14b5911..daa0e32 100644
--- a/qemu/hw/device-assignment.c
+++ b/qemu/hw/device-assignment.c
@@ -254,9 +254,26 @@ static int access_capability_config(AssignedDevice *pci_dev,
return 0;
}
+static void assigned_dev_enable_msi(AssignedDevice *assigned_dev);
+
static void check_cap_state(AssignedDevice *pci_dev,
uint32_t address, uint32_t* val)
{
+ uint32_t pos = pci_dev->cap.start;
+
+#ifdef KVM_CAP_DEVICE_MSI
+ /* Check if guest want to enable MSI */
+ if (pci_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
+ if (address == pos + 2 && (uint8_t)*val == 1) {
+ pci_dev->cap.enabled |= ASSIGNED_DEVICE_MSI_ENABLED;
+ assigned_dev_enable_msi(pci_dev);
+ if (!pci_dev->cap.enabled & ASSIGNED_DEVICE_MSI_ENABLED)
+ *val &= ~1ul;
+ return;
+ }
+ pos += ASSIGNED_DEVICE_CONFIG_MSI_LENGTH;
+ }
+#endif
return;
}
@@ -401,11 +418,13 @@ do_log:
DEBUG("(%x.%x): address=%04x val=0x%08x len=%d\n",
(d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len);
- /* kill the special capabilities */
- if (address == 4 && len == 4)
- val &= ~0x100000;
- else if (address == 6)
- val &= ~0x10;
+ if (!pci_dev->cap.available) {
+ /* kill the special capabilities */
+ if (address == 4 && len == 4)
+ val &= ~0x100000;
+ else if (address == 6)
+ val &= ~0x10;
+ }
return val;
}
@@ -583,6 +602,8 @@ void assigned_dev_update_irq(PCIDevice *d)
LIST_FOREACH(adev, &adev_head, next) {
assigned_dev = adev->assigned_dev;
+ if (assigned_dev->cap.enabled & ASSIGNED_DEVICE_MSI_ENABLED)
+ continue;
irq = pci_map_irq(&assigned_dev->dev, assigned_dev->intpin);
irq = piix_get_irq(irq);
@@ -613,10 +634,40 @@ void assigned_dev_update_irq(PCIDevice *d)
}
}
+#ifdef KVM_CAP_DEVICE_MSI
+static void assigned_dev_enable_msi(AssignedDevice *assigned_dev)
+{
+ int r;
+ struct kvm_assigned_irq assigned_irq_data;
+
+ 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.guest_msi.addr_lo = *(uint32_t *)
+ (assigned_dev->cap.config + 4);
+ assigned_irq_data.guest_msi.data = *(uint16_t *)
+ (assigned_dev->cap.config + 8);
+ assigned_irq_data.flags |= KVM_DEV_IRQ_ASSIGN_ENABLE_MSI;
+ r = kvm_assign_irq(kvm_context, &assigned_irq_data);
+ if (r < 0) {
+ perror("assigned_dev_enable_msi");
+ assigned_dev->cap.enabled &= ~ASSIGNED_DEVICE_MSI_ENABLED;
+ /* Fail to enable MSI, enable INTx instead */
+ assigned_dev_update_irq((PCIDevice *)assigned_dev);
+ }
+}
+#endif
+
static void init_dev_cap_config(AssignedDevice *dev)
{
#define ASSIGNED_DEVICE_CAPABILITY_START_ADDR 0x40
dev->cap.start = ASSIGNED_DEVICE_CAPABILITY_START_ADDR;
+#ifdef KVM_CAP_DEVICE_MSI
+ /* Expose MSI capability */
+ dev->cap.config[0] = 0x5;
+ dev->cap.length += ASSIGNED_DEVICE_CONFIG_MSI_LENGTH;
+#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 531a489..7e74287 100644
--- a/qemu/hw/device-assignment.h
+++ b/qemu/hw/device-assignment.h
@@ -86,7 +86,10 @@ typedef struct {
int available;
#define ASSIGNED_DEVICE_CAPABILITY_LENGTH 0x60
uint8_t config[ASSIGNED_DEVICE_CAPABILITY_LENGTH];
+#define ASSIGNED_DEVICE_CONFIG_MSI_LENGTH 0x10
unsigned int start, length;
+#define ASSIGNED_DEVICE_MSI_ENABLED (1 << 0)
+ int enabled;
} cap;
} AssignedDevice;
--
1.5.4.5
prev parent reply other threads:[~2008-11-21 9:08 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-21 9:04 [PATCH 0/4] Userspace for MSI support of KVM Sheng Yang
2008-11-21 9:04 ` [PATCH 1/4] Add dependence for libpci Sheng Yang
2008-11-21 9:04 ` [PATCH 2/4] Figure out device capability Sheng Yang
2008-11-21 9:04 ` [PATCH 3/4] Support for " Sheng Yang
2008-11-23 12:28 ` Avi Kivity
2008-11-24 7:24 ` Sheng Yang
2008-11-25 14:39 ` Avi Kivity
2008-11-21 9:04 ` 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=1227258267-22901-5-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.