[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[UNIKRAFT PATCH 1/2] plat/kvm: do not allocate IRQ handler entries dynamically



IRQ handler entries are currently allocated dynamically. This has two
undesired consequences: (1) this requires the dynamic memory allocator to
be initialized when ukplat_irq_init() is called, which happens quite early,
and (2) this makes the registering of IRQ handlers quite expensive.

Pre-allocate IRQ handles statically. Their number can be configured via a
new config variable KVM_MAX_IRQ_HANDLER_ENTRIES.

Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
---
 plat/kvm/Config.uk |  5 +++++
 plat/kvm/irq.c     | 40 ++++++++++++++++++++++------------------
 2 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/plat/kvm/Config.uk b/plat/kvm/Config.uk
index 3372b6c..fe4d8cf 100644
--- a/plat/kvm/Config.uk
+++ b/plat/kvm/Config.uk
@@ -65,6 +65,11 @@ endif
 
 endmenu
 
+config KVM_MAX_IRQ_HANDLER_ENTRIES
+       int "Maximum number of IRQ handlers per event"
+       default 8
+       depends on (ARCH_X86_64)
+
 config KVM_PCI
        bool "PCI Bus Driver"
        default y
diff --git a/plat/kvm/irq.c b/plat/kvm/irq.c
index 8f43aa6..1a8be10 100644
--- a/plat/kvm/irq.c
+++ b/plat/kvm/irq.c
@@ -27,7 +27,6 @@
 
 #include <stdlib.h>
 #include <uk/alloc.h>
-#include <uk/list.h>
 #include <uk/plat/lcpu.h>
 #include <uk/plat/common/cpu.h>
 #include <uk/plat/common/irq.h>
@@ -37,17 +36,21 @@
 #include <errno.h>
 #include <uk/bitops.h>
 
-static struct uk_alloc *allocator;
-
 struct irq_handler {
        irq_handler_func_t func;
        void *arg;
-
-       UK_SLIST_ENTRY(struct irq_handler) entries;
 };
 
-UK_SLIST_HEAD(irq_handler_head, struct irq_handler);
-static struct irq_handler_head irq_handlers[__MAX_IRQ];
+static struct irq_handler irq_handlers[__MAX_IRQ]
+                               [CONFIG_KVM_MAX_IRQ_HANDLER_ENTRIES];
+
+static inline struct irq_handler *allocate_handler(unsigned long irq)
+{
+       for (int i = 0; i < CONFIG_KVM_MAX_IRQ_HANDLER_ENTRIES; i++)
+               if (irq_handlers[irq][i].func == NULL)
+                       return &irq_handlers[irq][i];
+       return NULL;
+}
 
 int ukplat_irq_register(unsigned long irq, irq_handler_func_t func, void *arg)
 {
@@ -55,19 +58,17 @@ int ukplat_irq_register(unsigned long irq, 
irq_handler_func_t func, void *arg)
        unsigned long flags;
 
        UK_ASSERT(irq < __MAX_IRQ);
-       UK_ASSERT(allocator != NULL);
 
-       h = uk_malloc(allocator, sizeof(struct irq_handler));
+       flags = ukplat_lcpu_save_irqf();
+       h = allocate_handler(irq);
        if (!h)
-               return -ENOMEM;
+               UK_CRASH("Insufficient number of IRQ handler entries.\n");
 
        h->func = func;
-       h->arg = arg;
-
-       flags = ukplat_lcpu_save_irqf();
-       UK_SLIST_INSERT_HEAD(&irq_handlers[irq], h, entries);
        ukplat_lcpu_restore_irqf(flags);
 
+       h->arg = arg;
+
        intctrl_clear_irq(irq);
        return 0;
 }
@@ -81,8 +82,12 @@ extern unsigned long sched_have_pending_events;
 void _ukplat_irq_handle(unsigned long irq)
 {
        struct irq_handler *h;
+       int i;
 
-       UK_SLIST_FOREACH(h, &irq_handlers[irq], entries) {
+       for (i = 0; i < CONFIG_KVM_MAX_IRQ_HANDLER_ENTRIES; i++) {
+               if (irq_handlers[irq][i].func == NULL)
+                       break;
+               h = &irq_handlers[irq][i];
                /* TODO define platform wise macro for timer IRQ number */
                if (irq != 0)
                        /* IRQ 0 is reserved for a timer, responsible to
@@ -112,9 +117,8 @@ exit_ack:
        intctrl_ack_irq(irq);
 }
 
-int ukplat_irq_init(struct uk_alloc *a)
+int ukplat_irq_init(struct uk_alloc *a __unused)
 {
-       UK_ASSERT(allocator == NULL);
-       allocator = a;
+       /* Nothing for now */
        return 0;
 }
-- 
2.7.4




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.