mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
xen/arm: io: Use binary search for mmio handler lookup
As the number of I/O handlers increase, the overhead associated with linear lookup also increases. The system might have maximum of 144 (assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario, it would require 144 iterations for finding a matching handler. Now it is time for us to change from linear (complexity O(n)) to a binary search (complexity O(log n) for reducing mmio handler lookup overhead. Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org> Acked-by: Julien Grall <julien.grall@arm.com> Acked-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
e3eb84e33c
commit
8047e090f4
1 file changed
+24
-15
+24
-15
@@ -20,6 +20,7 @@
|
||||
#include <xen/lib.h>
|
||||
#include <xen/spinlock.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/sort.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/mmio.h>
|
||||
|
||||
@@ -70,27 +71,31 @@ static int handle_write(const struct mmio_handler *handler, struct vcpu *v,
|
||||
handler->priv);
|
||||
}
|
||||
|
||||
/* This function assumes that mmio regions are not overlapped */
|
||||
static int cmp_mmio_handler(const void *key, const void *elem)
|
||||
{
|
||||
const struct mmio_handler *handler0 = key;
|
||||
const struct mmio_handler *handler1 = elem;
|
||||
|
||||
if ( handler0->addr < handler1->addr )
|
||||
return -1;
|
||||
|
||||
if ( handler0->addr > (handler1->addr + handler1->size) )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mmio_handler *find_mmio_handler(struct domain *d,
|
||||
paddr_t gpa)
|
||||
{
|
||||
const struct mmio_handler *handler;
|
||||
unsigned int i;
|
||||
struct vmmio *vmmio = &d->arch.vmmio;
|
||||
struct mmio_handler key = {.addr = gpa};
|
||||
const struct mmio_handler *handler;
|
||||
|
||||
read_lock(&vmmio->lock);
|
||||
|
||||
for ( i = 0; i < vmmio->num_entries; i++ )
|
||||
{
|
||||
handler = &vmmio->handlers[i];
|
||||
|
||||
if ( (gpa >= handler->addr) &&
|
||||
(gpa < (handler->addr + handler->size)) )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i == vmmio->num_entries )
|
||||
handler = NULL;
|
||||
|
||||
handler = bsearch(&key, vmmio->handlers, vmmio->num_entries,
|
||||
sizeof(*handler), cmp_mmio_handler);
|
||||
read_unlock(&vmmio->lock);
|
||||
|
||||
return handler;
|
||||
@@ -131,6 +136,10 @@ void register_mmio_handler(struct domain *d,
|
||||
|
||||
vmmio->num_entries++;
|
||||
|
||||
/* Sort mmio handlers in ascending order based on base address */
|
||||
sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
|
||||
cmp_mmio_handler, NULL);
|
||||
|
||||
write_unlock(&vmmio->lock);
|
||||
}
|
||||
|
||||
|
||||