All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson@hp.com>
To: kvm@vger.kernel.org, sheng.yang@intel.com, mst@redhat.com,
	avi@redhat.com
Cc: alex.williamson@hp.com
Subject: [PATCH v7] kvm: Use a bitmap for tracking used GSIs
Date: Tue, 19 May 2009 14:48:56 -0600	[thread overview]
Message-ID: <20090519204753.8727.19196.stgit@dl380g6-3.ned.telco.ned.telco> (raw)
In-Reply-To: <20090513172350.8722.70990.stgit@dl380g6-3.ned.telco.ned.telco>

We're currently using a counter to track the most recent GSI we've
handed out.  This quickly hits KVM_MAX_IRQ_ROUTES when using device
assignment with a driver that regularly toggles the MSI enable bit
(such as Linux kernels 2.6.21-26).  This can mean only a few minutes
of usable run time.  Instead, track used GSIs in a bitmap.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
---

 v2: Added mutex to protect gsi bitmap
 v3: Updated for comments from Michael Tsirkin
     No longer depends on "[PATCH] kvm: device-assignment: Catch GSI overflow"
 v4: Fix gsi_bytes calculation noted by Sheng Yang
 v5: Remove mutex per Avi
     Fix negative gsi_count path per Michael
     Remove KVM_CAP_IRQ_ROUTING per Michael, ppc should still be protected
         by the KVM_IOAPIC_NUM_PINS check
 v6: Make use of ALIGN macro, per Michael
     Define KVM_IOAPIC_NUM_PINS if not already, per Michael
     Fix comment indent, per Michael
     Remove unused BITMAP_SIZE macro
 v7: Don't define KVM_IOAPIC_NUM_PINS, mark bitmap in common
         paths so we can stay blissfully ignorant of ioapics

 kvm/libkvm/kvm-common.h |    3 +-
 kvm/libkvm/libkvm.c     |   91 +++++++++++++++++++++++++++++++++++++----------
 2 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/kvm/libkvm/kvm-common.h b/kvm/libkvm/kvm-common.h
index 591fb53..c95c591 100644
--- a/kvm/libkvm/kvm-common.h
+++ b/kvm/libkvm/kvm-common.h
@@ -67,7 +67,8 @@ struct kvm_context {
 	struct kvm_irq_routing *irq_routes;
 	int nr_allocated_irq_routes;
 #endif
-	int max_used_gsi;
+	void *used_gsi_bitmap;
+	int max_gsi;
 };
 
 int kvm_alloc_kernel_memory(kvm_context_t kvm, unsigned long memory,
diff --git a/kvm/libkvm/libkvm.c b/kvm/libkvm/libkvm.c
index ba0a5d1..c5d6a7f 100644
--- a/kvm/libkvm/libkvm.c
+++ b/kvm/libkvm/libkvm.c
@@ -61,10 +61,32 @@
 #define DPRINTF(fmt, args...) do {} while (0)
 #endif
 
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
 
 int kvm_abi = EXPECTED_KVM_API_VERSION;
 int kvm_page_size;
 
+static inline void set_gsi(kvm_context_t kvm, unsigned int gsi)
+{
+	uint32_t *bitmap = kvm->used_gsi_bitmap;
+
+	if (gsi < kvm->max_gsi)
+		bitmap[gsi / 32] |= 1U << (gsi % 32);
+	else
+		DPRINTF("Invalid GSI %d\n");
+}
+
+static inline void clear_gsi(kvm_context_t kvm, unsigned int gsi)
+{
+	uint32_t *bitmap = kvm->used_gsi_bitmap;
+
+	if (gsi < kvm->max_gsi)
+		bitmap[gsi / 32] &= ~(1U << (gsi % 32));
+	else
+		DPRINTF("Invalid GSI %d\n");
+}
+
 struct slot_info {
 	unsigned long phys_addr;
 	unsigned long len;
@@ -285,7 +307,7 @@ kvm_context_t kvm_init(struct kvm_callbacks *callbacks,
 {
 	int fd;
 	kvm_context_t kvm;
-	int r;
+	int r, gsi_count;
 
 	fd = open("/dev/kvm", O_RDWR);
 	if (fd == -1) {
@@ -323,6 +345,23 @@ kvm_context_t kvm_init(struct kvm_callbacks *callbacks,
 	kvm->no_irqchip_creation = 0;
 	kvm->no_pit_creation = 0;
 
+	gsi_count = kvm_get_gsi_count(kvm);
+	if (gsi_count > 0) {
+		int gsi_bits, i;
+
+		/* Round up so we can search ints using ffs */
+		gsi_bits = ALIGN(gsi_count, 32);
+		kvm->used_gsi_bitmap = malloc(gsi_bits / 8);
+		if (!kvm->used_gsi_bitmap)
+			goto out_close;
+		memset(kvm->used_gsi_bitmap, 0, gsi_bits / 8);
+		kvm->max_gsi = gsi_bits;
+
+		/* Mark any over-allocated bits as already in use */
+		for (i = gsi_count; i < gsi_bits; i++)
+			set_gsi(kvm, i);
+	}
+
 	return kvm;
  out_close:
 	close(fd);
@@ -626,9 +665,6 @@ int kvm_get_dirty_pages(kvm_context_t kvm, unsigned long phys_addr, void *buf)
 	return kvm_get_map(kvm, KVM_GET_DIRTY_LOG, slot, buf);
 }
 
-#define ALIGN(x, y)  (((x)+(y)-1) & ~((y)-1))
-#define BITMAP_SIZE(m) (ALIGN(((m)/PAGE_SIZE), sizeof(long) * 8) / 8)
-
 int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr,
 			      unsigned long len, void *buf, void *opaque,
 			      int (*cb)(unsigned long start, unsigned long len,
@@ -1298,8 +1334,8 @@ int kvm_add_routing_entry(kvm_context_t kvm,
 	new->flags = entry->flags;
 	new->u = entry->u;
 
-	if (entry->gsi > kvm->max_used_gsi)
-		kvm->max_used_gsi = entry->gsi;
+	set_gsi(kvm, entry->gsi);
+
 	return 0;
 #else
 	return -ENOSYS;
@@ -1327,12 +1363,14 @@ int kvm_del_routing_entry(kvm_context_t kvm,
 {
 #ifdef KVM_CAP_IRQ_ROUTING
 	struct kvm_irq_routing_entry *e, *p;
-	int i, found = 0;
+	int i, gsi, found = 0;
+
+	gsi = entry->gsi;
 
 	for (i = 0; i < kvm->irq_routes->nr; ++i) {
 		e = &kvm->irq_routes->entries[i];
 		if (e->type == entry->type
-		    && e->gsi == entry->gsi) {
+		    && e->gsi == gsi) {
 			switch (e->type)
 			{
 			case KVM_IRQ_ROUTING_IRQCHIP: {
@@ -1363,8 +1401,19 @@ int kvm_del_routing_entry(kvm_context_t kvm,
 			default:
 				break;
 			}
-			if (found)
+			if (found) {
+				/* If there are no other users of this GSI
+				 * mark it available in the bitmap */
+				for (i = 0; i < kvm->irq_routes->nr; i++) {
+					e = &kvm->irq_routes->entries[i];
+					if (e->gsi == gsi)
+						break;
+				}
+				if (i == kvm->irq_routes->nr)
+					clear_gsi(kvm, gsi);
+
 				return 0;
+			}
 		}
 	}
 	return -ESRCH;
@@ -1406,17 +1455,19 @@ int kvm_commit_irq_routes(kvm_context_t kvm)
 
 int kvm_get_irq_route_gsi(kvm_context_t kvm)
 {
-#ifdef KVM_CAP_IRQ_ROUTING
-	if (kvm->max_used_gsi >= KVM_IOAPIC_NUM_PINS)  {
-	    if (kvm->max_used_gsi <= kvm_get_gsi_count(kvm))
-                return kvm->max_used_gsi + 1;
-            else
-                return -ENOSPC;
-        } else
-            return KVM_IOAPIC_NUM_PINS;
-#else
-	return -ENOSYS;
-#endif
+	int i, bit;
+	uint32_t *buf = kvm->used_gsi_bitmap;
+
+	/* Return the lowest unused GSI in the bitmap */
+	for (i = 0; i < kvm->max_gsi / 32; i++) {
+		bit = ffs(~buf[i]);
+		if (!bit)
+			continue;
+
+		return bit - 1 + i * 32;
+	}
+
+	return -ENOSPC;
 }
 
 #ifdef KVM_CAP_DEVICE_MSIX


  parent reply	other threads:[~2009-05-19 20:49 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-07 22:22 [PATCH] kvm: Use a bitmap for tracking used GSIs Alex Williamson
2009-05-08 22:31 ` [PATCH v2] " Alex Williamson
2009-05-12 19:39   ` Michael S. Tsirkin
2009-05-12 21:56     ` Alex Williamson
2009-05-12 22:07   ` [PATCH v3] " Alex Williamson
2009-05-13  3:30     ` Yang, Sheng
2009-05-13  3:42       ` Alex Williamson
2009-05-13  4:10         ` Alex Williamson
2009-05-13  4:15           ` Yang, Sheng
2009-05-13  4:41     ` [PATCH v4] " Alex Williamson
2009-05-13  4:58       ` Yang, Sheng
2009-05-13  9:47       ` Avi Kivity
2009-05-13 12:28         ` Alex Williamson
2009-05-13 12:35           ` Avi Kivity
2009-05-13 12:55             ` Alex Williamson
2009-05-13 13:00               ` Avi Kivity
2009-05-13 13:11                 ` Alex Williamson
2009-05-13 13:55                   ` Michael S. Tsirkin
2009-05-13 14:15                     ` Alex Williamson
2009-05-13 14:30                       ` Michael S. Tsirkin
2009-05-13 14:33                       ` Alex Williamson
2009-05-13 23:07                         ` Alex Williamson
2009-05-17 20:47                           ` Avi Kivity
2009-05-18 11:12                             ` Michael S. Tsirkin
2009-05-18 11:36                               ` Avi Kivity
2009-05-18 12:19                                 ` Michael S. Tsirkin
2009-05-18 12:33                                   ` Avi Kivity
2009-05-18 13:45                                     ` Michael S. Tsirkin
2009-05-18 13:55                                       ` Avi Kivity
2009-05-18 14:40                                         ` Michael S. Tsirkin
2009-05-18 14:46                                           ` Avi Kivity
2009-05-18 15:01                                             ` Michael S. Tsirkin
2009-05-18 15:08                                               ` Avi Kivity
2009-05-13 14:32       ` Michael S. Tsirkin
2009-05-13 15:13       ` [PATCH v5] " Alex Williamson
2009-05-13 16:05         ` Michael S. Tsirkin
2009-05-13 17:13           ` Alex Williamson
2009-05-17 20:51           ` Avi Kivity
2009-05-13 17:28         ` [PATCH v6] " Alex Williamson
2009-05-13 18:46           ` Michael S. Tsirkin
2009-05-17 20:54           ` Avi Kivity
2009-05-18 22:32             ` Alex Williamson
2009-05-19  8:01               ` Avi Kivity
2009-05-19 20:48           ` Alex Williamson [this message]
2009-05-20 11:55             ` [PATCH v7] " Avi Kivity
2009-05-13  7:03     ` [PATCH v3] " Michael S. Tsirkin
2009-05-13 12:15       ` Alex Williamson
2009-05-13  7:04     ` Michael S. Tsirkin
2009-05-13 12:19       ` Alex Williamson
2009-05-13 14:25         ` Michael S. Tsirkin
2009-05-17 20:49         ` Avi Kivity
2009-05-11 12:00 ` [PATCH] " Yang, Sheng
2009-05-12 18:45   ` Alex Williamson
2009-05-12 19:06     ` Alex Williamson
2009-05-12 19:10       ` Michael S. Tsirkin
2009-05-12 19:23         ` Alex Williamson

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=20090519204753.8727.19196.stgit@dl380g6-3.ned.telco.ned.telco \
    --to=alex.williamson@hp.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=sheng.yang@intel.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.