[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] xen/arm: Implement dynamic allocation of irq descriptors
Hello Vijay, On 23/02/15 13:04, Vijay Kilari wrote: > On Thu, Feb 19, 2015 at 7:33 PM, Julien Grall <julien.grall@xxxxxxxxxx> wrote: >> On 19/02/15 07:17, vijay.kilari@xxxxxxxxx wrote: >>> From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> >>> >>> For arm memory for 1024 irq descriptors are allocated >>> statically irrespective of number of interrupt supported >>> by the platform. >>> >>> With this patch, irq descriptors are allocated at run time >>> and managed using red-black tree. Functions to insert, search >>> and delete irq descriptor are implemented in xen/common/irq.c. >> >> I think we may want to allocate SPIs/SGIs/PPIs at boot time. This number >> will never change. We can avoid to always to allocate 1024 IRQs by using >> the number provided by the GIC. > > The irq descriptor is allocated when platform_get_irq() is called or > route_irq_to_guest() > only. So we are not allocating based on GIC. You didn't understand what I said... I was suggesting to allocate SPIs at boot time. Using an array for them allow us to access to IRQ desc in constant time. This may help interrupt latency. > BTW, I have a query regarding pending_irq[]. > > pending_irq[] structure is also allocated boot time. Shouldn't we > allocate similar to > irq descriptors?. In case of LPI's (ITS) interrupts we cannot pre-allocate the > GIC ITS supported number of pending_irq[] at boot time. pending_irqs is not allocated at boot time but at domain creation. I think we should consider to create a separate structure for LPI's. > If so, I propose to allocate pending_irq[] along with irq_descritor and > destroy > along with irq descriptor > >> >> [..] >> >>> void __cpuinit init_secondary_IRQ(void) >>> @@ -265,6 +269,7 @@ void release_irq(unsigned int irq, const void *dev_id) >>> >>> desc = irq_to_desc(irq); >>> >>> + ASSERT(desc != NULL); >> >> What happen if the code decides to try to free a non-existing IRQ on >> non-debug mode? It will just segfault... and bring a possible security >> issue. > > Should quietly return? Yes, of course. [..] >>> unsigned long flags; >>> int retval = 0; >>> >>> @@ -394,6 +406,23 @@ int route_irq_to_guest(struct domain *d, unsigned int >>> irq, >>> action->name = devname; >>> action->free_on_release = 1; >>> >>> + spin_lock(&rb_tree_desc_lock); >>> + desc = find_irq_desc(&desc_root, irq); >>> + >>> + if ( desc == NULL ) >>> + { >>> + /* Allocate descriptor and add to rb tree */ >>> + desc = xzalloc(struct irq_desc); >>> + if ( desc == NULL ) >>> + { >>> + spin_unlock(&rb_tree_desc_lock); >>> + return -ENOMEM; >>> + } >>> + init_irq_data(irq, desc); >>> + insert_irq_desc(&desc_root, irq, desc); >>> + } >>> + spin_unlock(&rb_tree_desc_lock); >>> + >> >> Why do you need this in route_irq_to_guest? > > For LPI's descriptors are allocated only on ITS command. In this > case we call route_irq_to_guest. So here we allocate memory for > descriptor We don't support LPIs right now, so this change doesn't make sense. Aside that, this is not the right place. route_irq_to_guest should route a validate physical IRQ to the guest. LPIs should have been created before, for instance while adding a new PCI. Otherwise, who will validate the validity of the LPIs? >> >>> spin_lock_irqsave(&desc->lock, flags); >>> >>> /* If the IRQ is already used by someone >>> @@ -470,13 +499,16 @@ static bool_t irq_validate_new_type(unsigned int >>> curr, unsigned new) >>> int irq_set_spi_type(unsigned int spi, unsigned int type) >>> { >>> unsigned long flags; >>> - struct irq_desc *desc = irq_to_desc(spi); >>> + struct irq_desc *desc = NULL; >>> int ret = -EBUSY; >>> >>> /* This function should not be used for other than SPIs */ >>> if ( spi < NR_LOCAL_IRQS ) >>> return -EINVAL; >>> >>> + desc = irq_to_desc(spi); >>> + ASSERT(desc != NULL); >>> + >>> spin_lock_irqsave(&desc->lock, flags); >>> >>> if ( !irq_validate_new_type(desc->arch.type, type) ) >>> @@ -532,6 +564,7 @@ int platform_get_irq(const struct dt_device_node >>> *device, int index) >>> { >>> struct dt_irq dt_irq; >>> unsigned int type, irq; >>> + struct irq_desc *desc; >>> int res; >>> >>> res = dt_device_get_irq(device, index, &dt_irq); >>> @@ -541,6 +574,22 @@ int platform_get_irq(const struct dt_device_node >>> *device, int index) >>> irq = dt_irq.irq; >>> type = dt_irq.type; >>> >>> + spin_lock(&rb_tree_desc_lock); >>> + desc = find_irq_desc(&desc_root, irq); >>> + if ( desc == NULL ) >>> + { >>> + /* Allocate descriptor for this irq */ >>> + desc = xzalloc(struct irq_desc); >>> + if ( desc == NULL ) >>> + { >>> + spin_unlock(&rb_tree_desc_lock); >>> + return -ENOMEM; >>> + } >>> + init_irq_data(irq, desc); >>> + insert_irq_desc(&desc_root, irq, desc); >>> + } >>> + spin_unlock(&rb_tree_desc_lock); >>> + >> >>> /* Setup the IRQ type */ >>> if ( irq < NR_LOCAL_IRQS ) >>> res = irq_local_set_type(irq, type); >>> diff --git a/xen/common/irq.c b/xen/common/irq.c >>> index 3e55dfa..ddf85c5 100644 >>> --- a/xen/common/irq.c >>> +++ b/xen/common/irq.c >>> @@ -40,3 +40,61 @@ unsigned int irq_startup_none(struct irq_desc *desc) >>> { >>> return 0; >>> } >>> + >>> +irq_desc_t * find_irq_desc( struct rb_root *root_node, int irq) >>> +{ >>> + struct rb_node *node = root_node->rb_node; >>> + >>> + while ( node ) >>> + { >>> + irq_desc_t *this; >>> + >>> + this = container_of(node, irq_desc_t, node); >>> + >>> + if ( irq < this->irq ) >>> + node = node->rb_left; >>> + else if (irq > this->irq) >>> + node = node->rb_right; >>> + else >>> + return this; >>> + } >>> + >>> + return NULL; >>> +} >>> + >>> +int insert_irq_desc(struct rb_root *root_node, int irq, struct irq_desc >>> *desc) >>> +{ >>> + struct rb_node **new, *parent; >>> + >>> + new = &root_node->rb_node; >>> + parent = NULL; >>> + >>> + while ( *new ) >>> + { >>> + irq_desc_t *this; >>> + >>> + this = container_of(*new, irq_desc_t, node); >>> + >>> + parent = *new; >>> + if ( desc->irq < this->irq ) >>> + new = &((*new)->rb_left); >>> + else if (desc->irq > this->irq) >>> + new = &((*new)->rb_right); >>> + else >>> + return -EEXIST; >>> + } >>> + >>> + rb_link_node(&desc->node, parent, new); >>> + rb_insert_color(&desc->node, root_node); >>> + >>> + return 0; >>> +} >>> + >>> +void delete_irq_desc(struct rb_root *root_node, int irq) >>> +{ >>> + struct irq_desc *desc; >>> + >>> + desc = find_irq_desc(root_node, irq); >>> + if ( desc ) >>> + rb_erase(&desc->node, root_node); >>> +} >> >> What's the matter to put this function on the common code when the >> variable itself lives in the architecture code? > > Which code is common here? Any file living in xen/common is part of the common code... Regards, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |