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

Re: [XenARM] [PATCH] arm: support fewer LRs register than virtual irqs



On Tue, 14 Feb 2012, Jenny Smith wrote:
> On Tue, Feb 14, 2012 at 1:07 PM, Stefano Stabellini
> <stefano.stabellini@xxxxxxxxxxxxx> wrote:
> > If the vgic needs to inject a virtual irq into the guest, but no free
> > LR registers are available, add the irq to a list and return.
> > Whenever an LR register becomes available we add the queued irq to it
> > and remove it from the list.
> > We use the gic lock to protect the list and the bitmask.
> >
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> > ---
> > Âxen/arch/arm/gic.c      |  46 
> > +++++++++++++++++++++++++++++++++++++----
> > Âxen/include/asm-arm/domain.h | Â Â1 +
> > Â2 files changed, 42 insertions(+), 5 deletions(-)
> >
> > diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> > index adc10bb..97c223c 100644
> > --- a/xen/arch/arm/gic.c
> > +++ b/xen/arch/arm/gic.c
> > @@ -25,6 +25,7 @@
> > Â#include <xen/sched.h>
> > Â#include <xen/errno.h>
> > Â#include <xen/softirq.h>
> > +#include <xen/list.h>
> > Â#include <asm/p2m.h>
> > Â#include <asm/domain.h>
> >
> > @@ -45,6 +46,8 @@ static struct {
> > Â Â unsigned int lines;
> > Â Â unsigned int cpus;
> > Â Â spinlock_t lock;
> > + Â Âuint64_t lr_mask;
> > + Â Âstruct list_head lr_pending;
> > Â} gic;
> >
> > Âirq_desc_t irq_desc[NR_IRQS];
> > @@ -247,6 +250,8 @@ static void __cpuinit gic_hyp_init(void)
> >
> > Â Â GICH[GICH_HCR] = GICH_HCR_EN;
> > Â Â GICH[GICH_MISR] = GICH_MISR_EOI;
> > + Â Âgic.lr_mask = 0ULL;
> > + Â ÂINIT_LIST_HEAD(&gic.lr_pending);
> > Â}
> >
> > Â/* Set up the GIC */
> > @@ -345,16 +350,35 @@ int __init setup_irq(unsigned int irq, struct 
> > irqaction *new)
> > Â Â return rc;
> > Â}
> >
> > -void gic_set_guest_irq(unsigned int virtual_irq,
> > +static inline void gic_set_lr(int lr, unsigned int virtual_irq,
> > Â Â Â Â unsigned int state, unsigned int priority)
> > Â{
> > - Â ÂBUG_ON(virtual_irq > nr_lrs);
> > - Â ÂGICH[GICH_LR + virtual_irq] = state |
> > + Â ÂBUG_ON(lr > nr_lrs);
> > + Â ÂGICH[GICH_LR + lr] = state |
> > Â Â Â Â GICH_LR_MAINTENANCE_IRQ |
> > Â Â Â Â ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) |
> > Â Â Â Â ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT);
> > Â}
> >
> > +void gic_set_guest_irq(unsigned int virtual_irq,
> > + Â Â Â Âunsigned int state, unsigned int priority)
> > +{
> > + Â Âint i;
> > +
> > + Â Âspin_lock(&gic.lock);
> > + Â Âfor (i = 0; i < nr_lrs; i++) {
> > + Â Â Â Âif (!test_and_set_bit(i, &gic.lr_mask))
> > + Â Â Â Â{
> > + Â Â Â Â Â Âgic_set_lr(i, virtual_irq, state, priority);
> > + Â Â Â Â Â Âspin_unlock(&gic.lock);
> > + Â Â Â Â Â Âreturn;
> > + Â Â Â Â}
> > + Â Â}
> > + Â Âlist_add_tail(&irq_to_pending(current, virtual_irq)->lr_link, 
> > &gic.lr_pending);
> > + Â Âspin_unlock(&gic.lock);
> > + Â Âreturn;
> > +}
> > +
> > Âvoid gic_inject_irq_start(void)
> > Â{
> > Â Â uint32_t hcr;
> > @@ -435,13 +459,26 @@ static void maintenance_interrupt(int irq, void 
> > *dev_id, struct cpu_user_regs *r
> > Â Â uint32_t lr;
> > Â Â uint64_t eisr = GICH[GICH_EISR0] | (((uint64_t) GICH[GICH_EISR1]) << 
> > 32);
> >
> > - Â Âfor ( i = 0; i < 64; i++ ) {
> > + Â Âfor ( i = 0; i < nr_lrs; i++ ) {
> > Â Â Â Â if ( eisr & ((uint64_t)1 << i) ) {
> > Â Â Â Â Â Â struct pending_irq *p;
> >
> > + Â Â Â Â Â Âspin_lock(&gic.lock);
> > Â Â Â Â Â Â lr = GICH[GICH_LR + i];
> > Â Â Â Â Â Â virq = lr & GICH_LR_VIRTUAL_MASK;
> > Â Â Â Â Â Â GICH[GICH_LR + i] = 0;
> > + Â Â Â Â Â Âclear_bit(i, &gic.lr_mask);
> > +
> > + Â Â Â Â Â Âif ( !list_empty(gic.lr_pending.next) ) {
> > + Â Â Â Â Â Â Â Âp = list_entry(gic.lr_pending.next, typeof(*p), lr_link);
> > + Â Â Â Â Â Â Â Âgic_set_lr(i, p->irq, GICH_LR_PENDING, p->priority);
> > + Â Â Â Â Â Â Â Âlist_del(&p->lr_link);
> > + Â Â Â Â Â Â Â ÂINIT_LIST_HEAD(&p->lr_link);
> > + Â Â Â Â Â Â Â Âset_bit(i, &gic.lr_mask);
> > + Â Â Â Â Â Â} else {
> > + Â Â Â Â Â Â Â Âgic_inject_irq_stop();
> > + Â Â Â Â Â Â}
> > + Â Â Â Â Â Âspin_unlock(&gic.lock);
> >
> > Â Â Â Â Â Â spin_lock(&current->arch.vgic.lock);
> > Â Â Â Â Â Â p = irq_to_pending(current, virq);
> > @@ -449,7 +486,6 @@ static void maintenance_interrupt(int irq, void 
> > *dev_id, struct cpu_user_regs *r
> > Â Â Â Â Â Â Â Â p->desc->status &= ~IRQ_INPROGRESS;
> > Â Â Â Â Â Â Â Â GICC[GICC_DIR] = virq;
> > Â Â Â Â Â Â }
> > - Â Â Â Â Â Âgic_inject_irq_stop();
> > Â Â Â Â Â Â list_del(&p->link);
> > Â Â Â Â Â Â INIT_LIST_HEAD(&p->link);
> > Â Â Â Â Â Â cpu_raise_softirq(current->processor, VGIC_SOFTIRQ);
> > diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> > index 3372d14..75095ff 100644
> > --- a/xen/include/asm-arm/domain.h
> > +++ b/xen/include/asm-arm/domain.h
> > @@ -21,6 +21,7 @@ struct pending_irq
> > Â Â struct irq_desc *desc; /* only set it the irq corresponds to a physical 
> > irq */
> > Â Â uint8_t priority;
> > Â Â struct list_head link;
> > + Â Âstruct list_head lr_link;
> > Â};
> >
> > Âstruct arch_domain
> > --
> > 1.7.8.3
> >
> 
> The patch fixes the BUG() call from gic_set_guest_irq() but now I'm
> getting another guest data abort error.
> I used the arm-tools-2 branch -> the GIC code looks slightly
> different? Which branch should I be using?

I would ignore the tools branch for the moment, that is only useful to
upstream tool patches at the moment.

Just switch to xen-unstable that has all the patches that you need to
boot xen and linux on the Cortex-A15 emulator.
_______________________________________________
Xen-arm mailing list
Xen-arm@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-arm

 


Rackspace

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