* [PATCH] xen/arm: Don't hardcode event channel IRQ
@ 2013-05-17 10:49 Julien Grall
2013-05-20 15:32 ` Ian Campbell
0 siblings, 1 reply; 6+ messages in thread
From: Julien Grall @ 2013-05-17 10:49 UTC (permalink / raw)
To: xen-devel
Cc: patches, Julien Grall, ian.campbell, andre.przywara,
Stefano.Stabellini
On some board the PPI 31 is already used by another device. Xen finds a free
slot by starting from the end of PPIs and decreasing.
For the moment, guest will use the same event channel IRQ number as dom0.
Move map_devices_from_device_tree before generating dom0 DTB, because the
latter function will use the IRQ found by the first function.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
xen/arch/arm/domain.c | 8 ++++-
xen/arch/arm/domain_build.c | 68 +++++++++++++++++++++++++++++++++--------
xen/arch/arm/gic.c | 2 +-
xen/include/asm-arm/domain.h | 2 ++
xen/include/asm-arm/event.h | 4 ++-
xen/include/asm-arm/gic.h | 3 --
xen/include/asm-arm/irq.h | 8 +++++
xen/include/xen/device_tree.h | 3 ++
8 files changed, 79 insertions(+), 19 deletions(-)
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 9ca44ea..ebd94d3 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -481,6 +481,10 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
d->arch.vpidr = boot_cpu_data.midr.bits;
d->arch.vmpidr = boot_cpu_data.mpidr.bits;
+ /* TODO: retrieve the evtchn IRQ from the guest DTS */
+ if ( d->domain_id )
+ d->arch.evtchn_irq = dom0->arch.evtchn_irq;
+
clear_page(d->shared_info);
share_xen_page_with_guest(
virt_to_page(d->shared_info), d, XENSHARE_writable);
@@ -636,6 +640,8 @@ void arch_dump_domain_info(struct domain *d)
{
struct vcpu *v;
+ printk("Event channel IRQ: %u\n", d->arch.evtchn_irq);
+
for_each_vcpu ( d, v )
{
gic_dump_info(v);
@@ -672,7 +678,7 @@ void vcpu_mark_events_pending(struct vcpu *v)
if ( already_pending )
return;
- vgic_vcpu_inject_irq(v, VGIC_IRQ_EVTCHN_CALLBACK, 1);
+ vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq, 1);
}
/*
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index b92c64b..f857e40 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -258,7 +258,9 @@ static int fdt_next_dom0_node(const void *fdt, int node,
return node;
}
-static void make_hypervisor_node(void *fdt, int addrcells, int sizecells)
+static void make_hypervisor_node(struct domain *d,
+ void *fdt, int addrcells,
+ int sizecells)
{
const char compat[] =
"xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
@@ -291,9 +293,12 @@ static void make_hypervisor_node(void *fdt, int addrcells, int sizecells)
* interrupts is evtchn upcall <1 15 0xf08>
* See linux Documentation/devicetree/bindings/arm/gic.txt
*/
+ BUG_ON(!irq_is_ppi(d->arch.evtchn_irq));
intr[0] = cpu_to_fdt32(1); /* is a PPI */
- intr[1] = cpu_to_fdt32(VGIC_IRQ_EVTCHN_CALLBACK - 16); /* PPIs start at 16 */
- intr[2] = cpu_to_fdt32(0xf08); /* Active-low level-sensitive */
+ intr[1] = cpu_to_fdt32(d->arch.evtchn_irq - FIRST_PPI_IRQ);
+ /* PPI attached for each CPU and active-low level-sensitive */
+ intr[2] = cpu_to_fdt32(((0xf) << DT_IRQ_TYPE_CPU_MASK_SHIFT) |
+ DT_IRQ_TYPE_LEVEL_LOW);
fdt_property(fdt, "interrupts", intr, sizeof(intr[0]) * 3);
@@ -348,14 +353,15 @@ static int write_nodes(struct domain *d, struct kernel_info *kinfo,
while ( last_depth-- >= 1 )
fdt_end_node(kinfo->fdt);
- make_hypervisor_node(kinfo->fdt, address_cells[0], size_cells[0]);
+ make_hypervisor_node(d, kinfo->fdt, address_cells[0], size_cells[0]);
fdt_end_node(kinfo->fdt);
return 0;
}
/* Map the device in the domain */
-static int map_device(struct domain *d, const struct dt_device_node *dev)
+static int map_device(struct domain *d, const struct dt_device_node *dev,
+ bool_t ppis[])
{
unsigned int nirq;
unsigned int naddr;
@@ -403,6 +409,9 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
DPRINT("irq %u = %u type = 0x%x\n", i, irq.irq, irq.type);
/* Don't check return because the IRQ can be use by multiple device */
gic_route_irq_to_guest(d, &irq, dt_node_name(dev));
+
+ if (irq_is_ppi(irq.irq))
+ ppis[irq.irq - FIRST_PPI_IRQ] = 1;
}
/* Map the address ranges */
@@ -434,7 +443,8 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
return 0;
}
-static int handle_node(struct domain *d, const struct dt_device_node *np)
+static int handle_node(struct domain *d, const struct dt_device_node *np,
+ bool_t ppis[])
{
const struct dt_device_node *child;
int res;
@@ -449,7 +459,7 @@ static int handle_node(struct domain *d, const struct dt_device_node *np)
if ( dt_device_used_by(np) != DOMID_XEN )
{
- res = map_device(d, np);
+ res = map_device(d, np, ppis);
if ( res )
return res;
@@ -457,7 +467,7 @@ static int handle_node(struct domain *d, const struct dt_device_node *np)
for ( child = np->child; child != NULL; child = child->sibling )
{
- res = handle_node(d, child);
+ res = handle_node(d, child, ppis);
if ( res )
return res;
}
@@ -467,9 +477,41 @@ static int handle_node(struct domain *d, const struct dt_device_node *np)
static int map_devices_from_device_tree(struct domain *d)
{
+ bool_t ppis[NR_PPI_IRQS] = {0};
+ int res;
+ unsigned int i;
+
ASSERT(dt_host && (dt_host->sibling == NULL));
- return handle_node(d, dt_host);
+ res = handle_node(d, dt_host, ppis);
+
+ /*
+ * Fill by hand timer IRQS ppis as we don't map it in Dom0
+ * We assume the host IRQs and the dom0 IRQs are the same for the timer.
+ */
+ for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
+ {
+ const struct dt_irq *irq = timer_dt_irq(i);
+
+ if ( irq_is_ppi(irq->irq) )
+ ppis[irq->irq - FIRST_PPI_IRQ] = 1;
+ }
+
+ /* Start from the last PPIs and decrease to find a free PPI */
+ for ( i = NR_PPI_IRQS; i != 0; i-- )
+ {
+ if ( !ppis[i - 1] )
+ break;
+ }
+
+ if ( i == 0 )
+ panic("Can't find a free PPI for the event channel IRQ\n");
+
+ d->arch.evtchn_irq = (i - 1) + FIRST_PPI_IRQ;
+
+ printk(XENLOG_INFO "DOM0 Event channel IRQ: %u\n", d->arch.evtchn_irq);
+
+ return res;
}
static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
@@ -546,16 +588,16 @@ int construct_dom0(struct domain *d)
d->max_pages = ~0U;
- rc = prepare_dtb(d, &kinfo);
+ map_devices_from_device_tree(d);
+ rc = platform_specific_mapping(d);
if ( rc < 0 )
return rc;
- rc = kernel_prepare(&kinfo);
+ rc = prepare_dtb(d, &kinfo);
if ( rc < 0 )
return rc;
- map_devices_from_device_tree(d);
- rc = platform_specific_mapping(d);
+ rc = kernel_prepare(&kinfo);
if ( rc < 0 )
return rc;
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 30bf8d1..aa2710c 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -682,7 +682,7 @@ int gic_events_need_delivery(void)
void gic_inject(void)
{
if ( vcpu_info(current, evtchn_upcall_pending) )
- vgic_vcpu_inject_irq(current, VGIC_IRQ_EVTCHN_CALLBACK, 1);
+ vgic_vcpu_inject_irq(current, current->domain->arch.evtchn_irq, 1);
gic_restore_pending_irqs(current);
if (!gic_events_need_delivery())
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index cb251cc..6fc3ddd 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -76,6 +76,8 @@ struct arch_domain
uint64_t offset;
} virt_timer_base;
+ unsigned int evtchn_irq; /* Event Channel IRQ */
+
struct {
/*
* Covers access to other members of this struct _except_ for
diff --git a/xen/include/asm-arm/event.h b/xen/include/asm-arm/event.h
index ed05901..f8e8297 100644
--- a/xen/include/asm-arm/event.h
+++ b/xen/include/asm-arm/event.h
@@ -9,7 +9,9 @@ void vcpu_mark_events_pending(struct vcpu *v);
static inline int local_events_need_delivery_nomask(void)
{
- struct pending_irq *p = irq_to_pending(current, VGIC_IRQ_EVTCHN_CALLBACK);
+ struct pending_irq *p;
+
+ p = irq_to_pending(current, current->domain->arch.evtchn_irq);
/* XXX: if the first interrupt has already been delivered, we should
* check whether any other interrupts with priority higher than the
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 513c1fc..fc18c9e 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -129,9 +129,6 @@
#define GICH_LR_CPUID_SHIFT 9
#define GICH_VTR_NRLRGS 0x3f
-/* XXX: write this into the DT */
-#define VGIC_IRQ_EVTCHN_CALLBACK 31
-
#ifndef __ASSEMBLY__
#include <xen/device_tree.h>
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 80ff68d..eeddd82 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -46,6 +46,14 @@ int __init request_dt_irq(const struct dt_irq *irq,
void *dev_id);
int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
+#define FIRST_PPI_IRQ 16
+#define NR_PPI_IRQS 16
+
+static inline bool_t irq_is_ppi(unsigned int irq)
+{
+ return ((irq >= FIRST_PPI_IRQ) && (irq < (FIRST_PPI_IRQ + NR_PPI_IRQS)));
+}
+
#endif /* _ASM_HW_IRQ_H */
/*
* Local variables:
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 5a2a5c6..f51f451 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -114,6 +114,9 @@ struct dt_device_node {
(DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
#define DT_IRQ_TYPE_SENSE_MASK 0x0000000f
+/* Cpu mask shift to the interrupt specifier (GIC specific) */
+#define DT_IRQ_TYPE_CPU_MASK_SHIFT 8
+
/**
* dt_irq - describe an IRQ in the device tree
* @irq: IRQ number
--
1.7.10.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] xen/arm: Don't hardcode event channel IRQ
2013-05-17 10:49 [PATCH] xen/arm: Don't hardcode event channel IRQ Julien Grall
@ 2013-05-20 15:32 ` Ian Campbell
2013-05-20 15:58 ` Julien Grall
0 siblings, 1 reply; 6+ messages in thread
From: Ian Campbell @ 2013-05-20 15:32 UTC (permalink / raw)
To: Julien Grall; +Cc: Stefano.Stabellini, andre.przywara, patches, xen-devel
On Fri, 2013-05-17 at 11:49 +0100, Julien Grall wrote:
> @@ -467,9 +477,41 @@ static int handle_node(struct domain *d, const struct dt_device_node *np)
>
> static int map_devices_from_device_tree(struct domain *d)
> {
> + bool_t ppis[NR_PPI_IRQS] = {0};
> + int res;
> + unsigned int i;
> +
> ASSERT(dt_host && (dt_host->sibling == NULL));
>
> - return handle_node(d, dt_host);
> + res = handle_node(d, dt_host, ppis);
> +
> + /*
> + * Fill by hand timer IRQS ppis as we don't map it in Dom0
> + * We assume the host IRQs and the dom0 IRQs are the same for the timer.
This seems a bit fragile, what happens if new interrupts are added in
the future?
Can the gic.c code not track the PPIs which are either assigned to Xen
or a guest?
Or perhaps better vgic.c should know if which if any IRQs are routed for
a given guest. We may need to add a function to allow the vtimer code to
reserve the virtual interrupts which it is going to use. Seems odd that
we don't have an existing equivalent to gic_route_irq_to_guest in
vtimer.c...
> + */
> + for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
> + {
> + const struct dt_irq *irq = timer_dt_irq(i);
> +
> + if ( irq_is_ppi(irq->irq) )
> + ppis[irq->irq - FIRST_PPI_IRQ] = 1;
> + }
> +
> + /* Start from the last PPIs and decrease to find a free PPI */
> + for ( i = NR_PPI_IRQS; i != 0; i-- )
> + {
> + if ( !ppis[i - 1] )
> + break;
> + }
> +
> + if ( i == 0 )
> + panic("Can't find a free PPI for the event channel IRQ\n");
> +
> + d->arch.evtchn_irq = (i - 1) + FIRST_PPI_IRQ;
> +
> + printk(XENLOG_INFO "DOM0 Event channel IRQ: %u\n", d->arch.evtchn_irq);
> +
> + return res;
> }
>
> static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
> @@ -546,16 +588,16 @@ int construct_dom0(struct domain *d)
>
> d->max_pages = ~0U;
>
> - rc = prepare_dtb(d, &kinfo);
> + map_devices_from_device_tree(d);
May as well make map_devices_from_device_tree void then, it seems ot
always succeeds or panics.
Ian.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] xen/arm: Don't hardcode event channel IRQ
2013-05-20 15:32 ` Ian Campbell
@ 2013-05-20 15:58 ` Julien Grall
2013-05-20 16:05 ` Ian Campbell
2013-05-30 8:12 ` Ian Campbell
0 siblings, 2 replies; 6+ messages in thread
From: Julien Grall @ 2013-05-20 15:58 UTC (permalink / raw)
To: Ian Campbell; +Cc: Stefano.Stabellini, andre.przywara, patches, xen-devel
On 05/20/2013 04:32 PM, Ian Campbell wrote:
> On Fri, 2013-05-17 at 11:49 +0100, Julien Grall wrote:
>> @@ -467,9 +477,41 @@ static int handle_node(struct domain *d, const struct dt_device_node *np)
>>
>> static int map_devices_from_device_tree(struct domain *d)
>> {
>> + bool_t ppis[NR_PPI_IRQS] = {0};
>> + int res;
>> + unsigned int i;
>> +
>> ASSERT(dt_host && (dt_host->sibling == NULL));
>>
>> - return handle_node(d, dt_host);
>> + res = handle_node(d, dt_host, ppis);
>> +
>> + /*
>> + * Fill by hand timer IRQS ppis as we don't map it in Dom0
>> + * We assume the host IRQs and the dom0 IRQs are the same for the timer.
>
> This seems a bit fragile, what happens if new interrupts are added in
> the future?
Right, but it's only for the timer as timer is "shared" between Xen and
dom0 (ie: we fake the timer IRQs).
> Can the gic.c code not track the PPIs which are either assigned to Xen
> or a guest?
> Or perhaps better vgic.c should know if which if any IRQs are routed for
> a given guest. We may need to add a function to allow the vtimer code to
> reserve the virtual interrupts which it is going to use. Seems odd that
> we don't have an existing equivalent to gic_route_irq_to_guest in
> vtimer.c...
vtimer will manually inject the virtual IRQ as IRQs are forwarded to the
running vCPU. gic_route_irq_to_guest will always route to a specific domain.
I though to add a new value for dt_used_by which parse the device node
IRQ/range but not map them in the domain. Because we don't need to know
if the IRQ is a PPI after the end of construct_dom0.
>> + */
>> + for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
>> + {
>> + const struct dt_irq *irq = timer_dt_irq(i);
>> +
>> + if ( irq_is_ppi(irq->irq) )
>> + ppis[irq->irq - FIRST_PPI_IRQ] = 1;
>> + }
>> +
>> + /* Start from the last PPIs and decrease to find a free PPI */
>> + for ( i = NR_PPI_IRQS; i != 0; i-- )
>> + {
>> + if ( !ppis[i - 1] )
>> + break;
>> + }
>> +
>> + if ( i == 0 )
>> + panic("Can't find a free PPI for the event channel IRQ\n");
>> +
>> + d->arch.evtchn_irq = (i - 1) + FIRST_PPI_IRQ;
>> +
>> + printk(XENLOG_INFO "DOM0 Event channel IRQ: %u\n", d->arch.evtchn_irq);
>> +
>> + return res;
>> }
>>
>> static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>> @@ -546,16 +588,16 @@ int construct_dom0(struct domain *d)
>>
>> d->max_pages = ~0U;
>>
>> - rc = prepare_dtb(d, &kinfo);
>> + map_devices_from_device_tree(d);
>
> May as well make map_devices_from_device_tree void then, it seems ot
> always succeeds or panics.
Will be fixed on the next version of the patch.
--
Julien
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] xen/arm: Don't hardcode event channel IRQ
2013-05-20 15:58 ` Julien Grall
@ 2013-05-20 16:05 ` Ian Campbell
2013-05-30 8:12 ` Ian Campbell
1 sibling, 0 replies; 6+ messages in thread
From: Ian Campbell @ 2013-05-20 16:05 UTC (permalink / raw)
To: Julien Grall; +Cc: Stefano.Stabellini, andre.przywara, patches, xen-devel
On Mon, 2013-05-20 at 16:58 +0100, Julien Grall wrote:
> On 05/20/2013 04:32 PM, Ian Campbell wrote:
>
> > On Fri, 2013-05-17 at 11:49 +0100, Julien Grall wrote:
> >> @@ -467,9 +477,41 @@ static int handle_node(struct domain *d, const struct dt_device_node *np)
> >>
> >> static int map_devices_from_device_tree(struct domain *d)
> >> {
> >> + bool_t ppis[NR_PPI_IRQS] = {0};
> >> + int res;
> >> + unsigned int i;
> >> +
> >> ASSERT(dt_host && (dt_host->sibling == NULL));
> >>
> >> - return handle_node(d, dt_host);
> >> + res = handle_node(d, dt_host, ppis);
> >> +
> >> + /*
> >> + * Fill by hand timer IRQS ppis as we don't map it in Dom0
> >> + * We assume the host IRQs and the dom0 IRQs are the same for the timer.
> >
> > This seems a bit fragile, what happens if new interrupts are added in
> > the future?
>
>
> Right, but it's only for the timer as timer is "shared" between Xen and
> dom0 (ie: we fake the timer IRQs).
Right now it is...
> > Can the gic.c code not track the PPIs which are either assigned to Xen
> > or a guest?
> > Or perhaps better vgic.c should know if which if any IRQs are routed for
> > a given guest. We may need to add a function to allow the vtimer code to
> > reserve the virtual interrupts which it is going to use. Seems odd that
> > we don't have an existing equivalent to gic_route_irq_to_guest in
> > vtimer.c...
>
>
> vtimer will manually inject the virtual IRQ as IRQs are forwarded to the
> running vCPU. gic_route_irq_to_guest will always route to a specific domain.
Right. My point was that there should be an equivalent to
gic_route_irq_to_guest which basically says "this IRQ is valid for this
domain (or vcpu) and I will be manually injecting this IRQ" without
routing a real IRQ to it i.e. some new vgic function which is called
from vcpu_vtimer_init().
Ian.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] xen/arm: Don't hardcode event channel IRQ
2013-05-20 15:58 ` Julien Grall
2013-05-20 16:05 ` Ian Campbell
@ 2013-05-30 8:12 ` Ian Campbell
2013-05-30 10:50 ` Julien Grall
1 sibling, 1 reply; 6+ messages in thread
From: Ian Campbell @ 2013-05-30 8:12 UTC (permalink / raw)
To: Julien Grall; +Cc: Stefano.Stabellini, andre.przywara, patches, xen-devel
On Mon, 2013-05-20 at 16:58 +0100, Julien Grall wrote:
> Will be fixed on the next version of the patch.
Did you resend this? If so then I'm afraid I've missed/lost it.
Ian.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] xen/arm: Don't hardcode event channel IRQ
2013-05-30 8:12 ` Ian Campbell
@ 2013-05-30 10:50 ` Julien Grall
0 siblings, 0 replies; 6+ messages in thread
From: Julien Grall @ 2013-05-30 10:50 UTC (permalink / raw)
To: Ian Campbell; +Cc: Stefano.Stabellini, andre.przywara, patches, xen-devel
On 05/30/2013 09:12 AM, Ian Campbell wrote:
> On Mon, 2013-05-20 at 16:58 +0100, Julien Grall wrote:
>> Will be fixed on the next version of the patch.
>
> Did you resend this? If so then I'm afraid I've missed/lost it.
Unfortunately not. I will try to resend it next week.
--
Julien
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2013-05-30 10:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-17 10:49 [PATCH] xen/arm: Don't hardcode event channel IRQ Julien Grall
2013-05-20 15:32 ` Ian Campbell
2013-05-20 15:58 ` Julien Grall
2013-05-20 16:05 ` Ian Campbell
2013-05-30 8:12 ` Ian Campbell
2013-05-30 10:50 ` Julien Grall
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).