[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 2/3] xen/arm: vgic: Keep track of vIRQ used by a domain
Hi Ian, On 19/01/15 15:55, Ian Campbell wrote: >> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c >> index 7221bc8..d0229d1 100644 >> --- a/xen/arch/arm/domain.c >> +++ b/xen/arch/arm/domain.c >> @@ -548,6 +548,9 @@ int arch_domain_create(struct domain *d, unsigned int >> domcr_flags) >> else >> d->arch.evtchn_irq = platform_dom0_evtchn_ppi(); >> >> + if ( !vgic_reserve_virq(d, d->arch.evtchn_irq) ) >> + BUG(); >> + >> /* >> * Virtual UART is only used by linux early printk and decompress code. >> * Only use it for the hardware domain because the linux kernel may not >> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c >> index c2dcb49..3d4f317 100644 >> --- a/xen/arch/arm/domain_build.c >> +++ b/xen/arch/arm/domain_build.c >> @@ -970,6 +970,12 @@ static int map_device(struct domain *d, struct >> dt_device_node *dev) >> irq = res; >> >> DPRINT("irq %u = %u\n", i, irq); >> + /* >> + * Checking the return of vgic_reserve_virq is not >> + * necessary. It should not fail except when we try to map >> + * twice the IRQ. This can happen if the IRQ is shared > > "to map the IRQ twice." > > Perhaps also "This can legitimately happen if the ..." (to make it clear > it is expected). Sounds better. I will fix it in the next version. >> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c >> index b272d86..1a8b3cd 100644 >> --- a/xen/arch/arm/vgic.c >> +++ b/xen/arch/arm/vgic.c >> @@ -110,6 +110,15 @@ int domain_vgic_init(struct domain *d) >> >> d->arch.vgic.handler->domain_init(d); >> >> + d->arch.vgic.allocated_irqs = >> + xzalloc_array(unsigned long, BITS_TO_LONGS(vgic_num_irqs(d))); >> + if ( !d->arch.vgic.allocated_irqs ) >> + return -ENOMEM; >> + >> + /* vIRQ0-15 (SGIs) are reserved */ >> + for ( i = 0; i <= 15; i++ ) > > ... ; i < NR_GIC_SGI; ... I don't really like the idea to use NR_GIC_SGI here. You are assuming that SGI is always start from 0. I will introduce GIC_SGI_FIRST, GIC_SGI_END and maybe the same for PPIs/SPIs. > >> + set_bit(i, d->arch.vgic.allocated_irqs); >> + >> return 0; >> } >> >> @@ -122,6 +131,7 @@ void domain_vgic_free(struct domain *d) >> { >> xfree(d->arch.vgic.shared_irqs); >> xfree(d->arch.vgic.pending_irqs); >> + xfree(d->arch.vgic.allocated_irqs); >> } >> >> int vcpu_vgic_init(struct vcpu *v) >> @@ -452,6 +462,54 @@ int vgic_emulate(struct cpu_user_regs *regs, union hsr >> hsr) >> return v->domain->arch.vgic.handler->emulate_sysreg(regs, hsr); >> } >> >> +bool_t vgic_reserve_virq(struct domain *d, unsigned int virq) >> +{ >> + bool_t reserved; >> + >> + if ( virq >= vgic_num_irqs(d) ) >> + return 0; >> + >> + reserved = !test_and_set_bit(virq, d->arch.vgic.allocated_irqs); >> + >> + return reserved; > > Can just return !test_and... directly. (I don't think you add anything > between these in the next patch?) Yes. It's a left-over of the spinlock solution in V1. > >> +} >> + >> +int vgic_allocate_virq(struct domain *d, bool_t spi) >> +{ >> + int ret; >> + int first, end; >> + unsigned int virq; >> + >> +retry: >> + if ( !spi ) >> + { >> + /* We only allocate PPIs. SGIs are all reserved */ >> + first = 16; >> + end = 32; >> + } >> + else >> + { >> + first = 32; >> + end = vgic_num_irqs(d); >> + } > > I think retry: could be at least here not way above, couldn't it? Yes. > In any case rather than goto can you use a while loop or some other > proper looping construct please, something like this ought to work: > > virq = first > while ( (virq = find_next...) < end ) > { > if ( test_and_set... ) > return virq; > first = virq; /* +1 ? */ > } > > or perhaps: > > for ( virq = first ; virq = find... ; first = virq ) > { > .... > } > > I think you might also be able combine virq and first into a single > variable? Unless always searching from the beginning is a feature? The goal was to avoid race condition with vgic_reserver_virq. In second though, we could also avoid to retry ad the raise condition would happen in very rare case. > >> diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h >> index 74d5a4e..5ddea51 100644 >> --- a/xen/include/asm-arm/vgic.h >> +++ b/xen/include/asm-arm/vgic.h >> @@ -199,6 +199,19 @@ extern int vgic_to_sgi(struct vcpu *v, register_t sgir, >> enum gic_sgi_mode irqmode, int virq, >> unsigned long vcpu_mask); >> extern void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned >> int irq); >> + >> +/* Reserve a specific guest vIRQ */ >> +extern bool_t vgic_reserve_virq(struct domain *d, unsigned int virq); >> + >> +/* >> + * Allocate a guest VIRQ >> + * - spi == 0 => allocate a PPI. It will be the same on every vCPU > > The second sentence makes me think I should somehow call this per-vcpu > and expect the same value to be returned each time, which isn't true > (nor possible given the api as it stands). I think you can assume > familiarity with PPI vs SGI in the context. > > Personally I'd prefer vgic_allocate_{ppi,spi} as a wrapper round a > common helper over potentially opaque bool arguments to functions. > Writing "0 /* ppi */" or "1 /* spi */" at the callers would be a > reasonable alternative if you don't want to do that. Good point, I will introduce wrappers. >> + * - spi == 1 => allocate an SGI >> + */ > > SGI != SPI. Oops. 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 |