ia64/xen-unstable
changeset 2932:cbdc0480194e
bitkeeper revision 1.1159.1.401 (41923739R6r2c-dNxHPSxOagRn-R3g)
Setup cpu-local interrupt handline.
Add support for ipi event channels.
Setup cpu-local interrupt handline.
Add support for ipi event channels.
author | cl349@freefall.cl.cam.ac.uk |
---|---|
date | Wed Nov 10 15:43:53 2004 +0000 (2004-11-10) |
parents | b12c5094e28c |
children | 23aab6d318e5 |
files | linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h xen/common/event_channel.c xen/common/keyhandler.c xen/include/public/event_channel.h xen/include/xen/sched.h |
line diff
1.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Nov 10 14:32:43 2004 +0000 1.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Nov 10 15:43:53 2004 +0000 1.3 @@ -441,6 +441,32 @@ int cpucount; 1.4 1.5 extern int cpu_idle(void); 1.6 1.7 + 1.8 +static irqreturn_t local_debug_interrupt(int irq, void *dev_id, 1.9 + struct pt_regs *regs) 1.10 +{ 1.11 + xxprint("local_debug_interrupt\n"); 1.12 + 1.13 + return IRQ_HANDLED; 1.14 +} 1.15 + 1.16 +static struct irqaction local_irq_debug = { 1.17 + local_debug_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ldebug", 1.18 + NULL, NULL 1.19 +}; 1.20 + 1.21 +void local_setup_debug(void) 1.22 +{ 1.23 + int time_irq; 1.24 + 1.25 + time_irq = bind_virq_to_irq(VIRQ_DEBUG); 1.26 + (void)setup_irq(time_irq, &local_irq_debug); 1.27 +} 1.28 + 1.29 + 1.30 +extern void setup_misdirect_virq(void); 1.31 +extern void local_setup_timer(void); 1.32 + 1.33 /* 1.34 * Activate a secondary processor. 1.35 */ 1.36 @@ -455,29 +481,18 @@ int __init start_secondary(void *unused) 1.37 smp_callin(); 1.38 while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) 1.39 rep_nop(); 1.40 -#if 1 1.41 - if (0) { 1.42 - char *msg = "start_secondary\n"; 1.43 - char *msg2 = "delay2\n"; 1.44 - int timeout; 1.45 - (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg); 1.46 - for (timeout = 0; timeout < 50000; timeout++) { 1.47 - udelay(100); 1.48 - if (timeout == 20000) { 1.49 - (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg2), msg2); 1.50 - timeout = 0; 1.51 - } 1.52 - } 1.53 - } 1.54 - // enable_APIC_timer(); 1.55 + setup_misdirect_virq(); 1.56 + local_setup_timer(); 1.57 + local_setup_debug(); /* XXX */ 1.58 + local_irq_enable(); 1.59 /* 1.60 * low-memory mappings have been cleared, flush them from 1.61 * the local TLBs too. 1.62 */ 1.63 - // local_flush_tlb(); 1.64 + local_flush_tlb(); 1.65 cpu_set(smp_processor_id(), cpu_online_map); 1.66 wmb(); 1.67 - if (10) { 1.68 + if (01) { 1.69 char *msg2 = "delay2\n"; 1.70 int timeout; 1.71 for (timeout = 0; timeout < 50000; timeout++) { 1.72 @@ -489,32 +504,6 @@ int __init start_secondary(void *unused) 1.73 } 1.74 } 1.75 return cpu_idle(); 1.76 -#else 1.77 - /* 1.78 - * Dont put anything before smp_callin(), SMP 1.79 - * booting is too fragile that we want to limit the 1.80 - * things done here to the most necessary things. 1.81 - */ 1.82 - cpu_init(); 1.83 - smp_callin(); 1.84 - while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) 1.85 - rep_nop(); 1.86 - setup_secondary_APIC_clock(); 1.87 - if (nmi_watchdog == NMI_IO_APIC) { 1.88 - disable_8259A_irq(0); 1.89 - enable_NMI_through_LVT0(NULL); 1.90 - enable_8259A_irq(0); 1.91 - } 1.92 - enable_APIC_timer(); 1.93 - /* 1.94 - * low-memory mappings have been cleared, flush them from 1.95 - * the local TLBs too. 1.96 - */ 1.97 - local_flush_tlb(); 1.98 - cpu_set(smp_processor_id(), cpu_online_map); 1.99 - wmb(); 1.100 - return cpu_idle(); 1.101 -#endif 1.102 } 1.103 1.104 /*
2.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c Wed Nov 10 14:32:43 2004 +0000 2.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/time.c Wed Nov 10 15:43:53 2004 +0000 2.3 @@ -702,6 +702,35 @@ void time_resume(void) 2.4 last_update_from_xen = 0; 2.5 } 2.6 2.7 +#ifdef CONFIG_SMP 2.8 +static irqreturn_t local_timer_interrupt(int irq, void *dev_id, 2.9 + struct pt_regs *regs) 2.10 +{ 2.11 + static int xxx = 0; 2.12 + if ((xxx++ % 100) == 0) 2.13 + xxprint("local_timer_interrupt\n"); 2.14 + 2.15 + /* XXX add processed_system_time loop thingy */ 2.16 + if (regs) 2.17 + update_process_times(user_mode(regs)); 2.18 + 2.19 + return IRQ_HANDLED; 2.20 +} 2.21 + 2.22 +static struct irqaction local_irq_timer = { 2.23 + local_timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ltimer", 2.24 + NULL, NULL 2.25 +}; 2.26 + 2.27 +void local_setup_timer(void) 2.28 +{ 2.29 + int time_irq; 2.30 + 2.31 + time_irq = bind_virq_to_irq(VIRQ_TIMER); 2.32 + (void)setup_irq(time_irq, &local_irq_timer); 2.33 +} 2.34 +#endif 2.35 + 2.36 /* 2.37 * /proc/sys/xen: This really belongs in another file. It can stay here for 2.38 * now however.
3.1 --- a/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c Wed Nov 10 14:32:43 2004 +0000 3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c Wed Nov 10 15:43:53 2004 +0000 3.3 @@ -61,7 +61,11 @@ static int evtchn_to_irq[NR_EVENT_CHANNE 3.4 static int irq_to_evtchn[NR_IRQS]; 3.5 3.6 /* IRQ <-> VIRQ mapping. */ 3.7 -static int virq_to_irq[NR_VIRQS]; 3.8 +DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]); 3.9 + 3.10 +#define NR_IPIS 8 3.11 +/* IRQ <-> IPI mapping. */ 3.12 +DEFINE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]); 3.13 3.14 /* Reference counts for bindings to IRQs. */ 3.15 static int irq_bindcount[NR_IRQS]; 3.16 @@ -141,10 +145,11 @@ int bind_virq_to_irq(int virq) 3.17 { 3.18 evtchn_op_t op; 3.19 int evtchn, irq; 3.20 + int cpu = smp_processor_id(); 3.21 3.22 spin_lock(&irq_mapping_update_lock); 3.23 3.24 - if ( (irq = virq_to_irq[virq]) == -1 ) 3.25 + if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 ) 3.26 { 3.27 op.cmd = EVTCHNOP_bind_virq; 3.28 op.u.bind_virq.virq = virq; 3.29 @@ -156,7 +161,7 @@ int bind_virq_to_irq(int virq) 3.30 evtchn_to_irq[evtchn] = irq; 3.31 irq_to_evtchn[irq] = evtchn; 3.32 3.33 - virq_to_irq[virq] = irq; 3.34 + per_cpu(virq_to_irq, cpu)[virq] = irq; 3.35 } 3.36 3.37 irq_bindcount[irq]++; 3.38 @@ -169,7 +174,8 @@ int bind_virq_to_irq(int virq) 3.39 void unbind_virq_from_irq(int virq) 3.40 { 3.41 evtchn_op_t op; 3.42 - int irq = virq_to_irq[virq]; 3.43 + int cpu = smp_processor_id(); 3.44 + int irq = per_cpu(virq_to_irq, cpu)[virq]; 3.45 int evtchn = irq_to_evtchn[irq]; 3.46 3.47 spin_lock(&irq_mapping_update_lock); 3.48 @@ -184,12 +190,48 @@ void unbind_virq_from_irq(int virq) 3.49 3.50 evtchn_to_irq[evtchn] = -1; 3.51 irq_to_evtchn[irq] = -1; 3.52 - virq_to_irq[virq] = -1; 3.53 + per_cpu(virq_to_irq, cpu)[virq] = -1; 3.54 } 3.55 3.56 spin_unlock(&irq_mapping_update_lock); 3.57 } 3.58 3.59 +void bind_ipi_on_cpu(int cpu, int ipi) 3.60 +{ 3.61 + evtchn_op_t op; 3.62 + 3.63 + spin_lock(&irq_mapping_update_lock); 3.64 + 3.65 + if (per_cpu(ipi_to_evtchn, cpu)[ipi] == 0) { 3.66 + op.cmd = EVTCHNOP_bind_ipi; 3.67 + op.u.bind_ipi.ipi_edom = cpu; 3.68 + if ( HYPERVISOR_event_channel_op(&op) != 0 ) 3.69 + panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu); 3.70 + 3.71 + per_cpu(ipi_to_evtchn, cpu)[ipi] = op.u.bind_ipi.port; 3.72 + } 3.73 + 3.74 + spin_unlock(&irq_mapping_update_lock); 3.75 +} 3.76 + 3.77 +void unbind_ipi_on_cpu(int cpu, int ipi) 3.78 +{ 3.79 + evtchn_op_t op; 3.80 + int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]; 3.81 + 3.82 + spin_lock(&irq_mapping_update_lock); 3.83 + 3.84 + op.cmd = EVTCHNOP_close; 3.85 + op.u.close.dom = DOMID_SELF; 3.86 + op.u.close.port = evtchn; 3.87 + if ( HYPERVISOR_event_channel_op(&op) != 0 ) 3.88 + panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu); 3.89 + 3.90 + per_cpu(ipi_to_evtchn, cpu)[ipi] = 0; 3.91 + 3.92 + spin_unlock(&irq_mapping_update_lock); 3.93 +} 3.94 + 3.95 int bind_evtchn_to_irq(int evtchn) 3.96 { 3.97 int irq; 3.98 @@ -414,6 +456,11 @@ static struct irqaction misdirect_action 3.99 NULL 3.100 }; 3.101 3.102 +void setup_misdirect_virq(void) 3.103 +{ 3.104 + (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action); 3.105 +} 3.106 + 3.107 static irqreturn_t xen_dbg(int irq, void *dev_id, struct pt_regs *regs) 3.108 { 3.109 char *msg = "debug\n"; 3.110 @@ -433,11 +480,12 @@ static struct irqaction xen_action = { 3.111 void irq_suspend(void) 3.112 { 3.113 int pirq, virq, irq, evtchn; 3.114 + int cpu = smp_processor_id(); /* XXX */ 3.115 3.116 /* Unbind VIRQs from event channels. */ 3.117 for ( virq = 0; virq < NR_VIRQS; virq++ ) 3.118 { 3.119 - if ( (irq = virq_to_irq[virq]) == -1 ) 3.120 + if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 ) 3.121 continue; 3.122 evtchn = irq_to_evtchn[irq]; 3.123 3.124 @@ -457,13 +505,14 @@ void irq_resume(void) 3.125 { 3.126 evtchn_op_t op; 3.127 int virq, irq, evtchn; 3.128 + int cpu = smp_processor_id(); /* XXX */ 3.129 3.130 for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ ) 3.131 mask_evtchn(evtchn); /* New event-channel space is not 'live' yet. */ 3.132 3.133 for ( virq = 0; virq < NR_VIRQS; virq++ ) 3.134 { 3.135 - if ( (irq = virq_to_irq[virq]) == -1 ) 3.136 + if ( (irq = per_cpu(virq_to_irq, cpu)[virq]) == -1 ) 3.137 continue; 3.138 3.139 /* Get a new binding from Xen. */ 3.140 @@ -485,12 +534,14 @@ void irq_resume(void) 3.141 void __init init_IRQ(void) 3.142 { 3.143 int i; 3.144 + int cpu; 3.145 3.146 spin_lock_init(&irq_mapping_update_lock); 3.147 3.148 /* No VIRQ -> IRQ mappings. */ 3.149 - for ( i = 0; i < NR_VIRQS; i++ ) 3.150 - virq_to_irq[i] = -1; 3.151 + for ( cpu = 0; cpu < NR_CPUS; cpu++ ) 3.152 + for ( i = 0; i < NR_VIRQS; i++ ) 3.153 + per_cpu(virq_to_irq, cpu)[i] = -1; 3.154 3.155 /* No event-channel -> IRQ mappings. */ 3.156 for ( i = 0; i < NR_EVENT_CHANNELS; i++ ) 3.157 @@ -525,7 +576,7 @@ void __init init_IRQ(void) 3.158 irq_desc[pirq_to_irq(i)].handler = &pirq_type; 3.159 } 3.160 3.161 - (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action); 3.162 + (void)setup_misdirect_virq(); 3.163 3.164 printk("debug_int\n"); 3.165 (void)setup_irq(bind_virq_to_irq(VIRQ_DEBUG), &xen_action);
4.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h Wed Nov 10 14:32:43 2004 +0000 4.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h Wed Nov 10 15:43:53 2004 +0000 4.3 @@ -138,6 +138,8 @@ 4.4 /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ 4.5 extern int bind_virq_to_irq(int virq); 4.6 extern void unbind_virq_from_irq(int virq); 4.7 +extern int bind_ipi_on_cpu(int cpu, int ipi); 4.8 +extern void unbind_ipi_on_cpu(int cpu, int ipi); 4.9 extern int bind_evtchn_to_irq(int evtchn); 4.10 extern void unbind_evtchn_from_irq(int evtchn); 4.11
5.1 --- a/xen/common/event_channel.c Wed Nov 10 14:32:43 2004 +0000 5.2 +++ b/xen/common/event_channel.c Wed Nov 10 15:43:53 2004 +0000 5.3 @@ -270,6 +270,33 @@ static long evtchn_bind_virq(evtchn_bind 5.4 return port; 5.5 5.6 bind->port = port; 5.7 + printk("evtchn_bind_virq %d/%d virq %d -> %d\n", 5.8 + d->id, ed->eid, virq, port); 5.9 + return 0; 5.10 +} 5.11 + 5.12 +static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind) 5.13 +{ 5.14 + struct exec_domain *ed = current; 5.15 + struct domain *d = ed->domain; 5.16 + int port, ipi_edom = bind->ipi_edom; 5.17 + 5.18 + spin_lock(&d->event_channel_lock); 5.19 + 5.20 + if ( (port = get_free_port(d)) >= 0 ) 5.21 + { 5.22 + d->event_channel[port].state = ECS_IPI; 5.23 + d->event_channel[port].u.ipi_edom = ipi_edom; 5.24 + } 5.25 + 5.26 + spin_unlock(&d->event_channel_lock); 5.27 + 5.28 + if ( port < 0 ) 5.29 + return port; 5.30 + 5.31 + bind->port = port; 5.32 + printk("evtchn_bind_ipi %d/%d ipi_edom %d -> %d\n", 5.33 + d->id, current->eid, ipi_edom, port); 5.34 return 0; 5.35 } 5.36 5.37 @@ -307,6 +334,8 @@ static long evtchn_bind_pirq(evtchn_bind 5.38 return rc; 5.39 5.40 bind->port = port; 5.41 + printk("evtchn_bind_pirq %d/%d pirq %d -> port %d\n", 5.42 + d->id, current->eid, pirq, port); 5.43 return 0; 5.44 } 5.45 5.46 @@ -352,6 +381,9 @@ static long __evtchn_close(struct domain 5.47 ed->virq_to_evtchn[chn1[port1].u.virq] = 0; 5.48 break; 5.49 5.50 + case ECS_IPI: 5.51 + break; 5.52 + 5.53 case ECS_INTERDOMAIN: 5.54 if ( d2 == NULL ) 5.55 { 5.56 @@ -516,6 +548,10 @@ static long evtchn_status(evtchn_status_ 5.57 status->status = EVTCHNSTAT_virq; 5.58 status->u.virq = chn[port].u.virq; 5.59 break; 5.60 + case ECS_IPI: 5.61 + status->status = EVTCHNSTAT_ipi; 5.62 + status->u.ipi_edom = chn[port].u.ipi_edom; 5.63 + break; 5.64 default: 5.65 BUG(); 5.66 } 5.67 @@ -555,6 +591,12 @@ long do_event_channel_op(evtchn_op_t *uo 5.68 rc = -EFAULT; /* Cleaning up here would be a mess! */ 5.69 break; 5.70 5.71 + case EVTCHNOP_bind_ipi: 5.72 + rc = evtchn_bind_ipi(&op.u.bind_ipi); 5.73 + if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) ) 5.74 + rc = -EFAULT; /* Cleaning up here would be a mess! */ 5.75 + break; 5.76 + 5.77 case EVTCHNOP_bind_pirq: 5.78 rc = evtchn_bind_pirq(&op.u.bind_pirq); 5.79 if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
6.1 --- a/xen/common/keyhandler.c Wed Nov 10 14:32:43 2004 +0000 6.2 +++ b/xen/common/keyhandler.c Wed Nov 10 15:43:53 2004 +0000 6.3 @@ -107,15 +107,14 @@ void do_task_queues(unsigned char key) 6.4 ed->ed_flags, 6.5 ed->vcpu_info->evtchn_upcall_pending, 6.6 ed->vcpu_info->evtchn_upcall_mask); 6.7 + printk("Notifying guest... %d/%d\n", d->id, ed->eid); 6.8 + printk("port %d/%d stat %d %d %d\n", 6.9 + VIRQ_DEBUG, ed->virq_to_evtchn[VIRQ_DEBUG], 6.10 + test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_pending[0]), 6.11 + test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_mask[0]), 6.12 + test_bit(ed->virq_to_evtchn[VIRQ_DEBUG]>>5, &ed->vcpu_info->evtchn_pending_sel)); 6.13 + send_guest_virq(ed, VIRQ_DEBUG); 6.14 } 6.15 - ed = d->exec_domain[0]; 6.16 - printk("Notifying guest... %d/%d\n", d->id, ed->eid); 6.17 - printk("port %d/%d stat %d %d %d\n", 6.18 - VIRQ_DEBUG, ed->virq_to_evtchn[VIRQ_DEBUG], 6.19 - test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_pending[0]), 6.20 - test_bit(ed->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_mask[0]), 6.21 - test_bit(ed->virq_to_evtchn[VIRQ_DEBUG]>>5, &ed->vcpu_info->evtchn_pending_sel)); 6.22 - send_guest_virq(d->exec_domain[0], VIRQ_DEBUG); 6.23 } 6.24 6.25 read_unlock(&domlist_lock);
7.1 --- a/xen/include/public/event_channel.h Wed Nov 10 14:32:43 2004 +0000 7.2 +++ b/xen/include/public/event_channel.h Wed Nov 10 15:43:53 2004 +0000 7.3 @@ -128,6 +128,7 @@ typedef struct { 7.4 #define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */ 7.5 #define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */ 7.6 #define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */ 7.7 +#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */ 7.8 u32 status; /* 8 */ 7.9 union { /* 12 */ 7.10 struct { 7.11 @@ -140,9 +141,22 @@ typedef struct { 7.12 } PACKED interdomain; /* EVTCHNSTAT_interdomain */ 7.13 u32 pirq; /* EVTCHNSTAT_pirq */ /* 12 */ 7.14 u32 virq; /* EVTCHNSTAT_virq */ /* 12 */ 7.15 + u32 ipi_edom; /* EVTCHNSTAT_ipi */ /* 12 */ 7.16 } PACKED u; 7.17 } PACKED evtchn_status_t; /* 20 bytes */ 7.18 7.19 +/* 7.20 + * EVTCHNOP_bind_ipi: Bind a local event channel to receive events. 7.21 + */ 7.22 +#define EVTCHNOP_bind_ipi 7 7.23 +typedef struct { 7.24 + /* IN parameters. */ 7.25 + u32 ipi_edom; /* 0 */ 7.26 + /* OUT parameters. */ 7.27 + u32 port; /* 4 */ 7.28 +} PACKED evtchn_bind_ipi_t; /* 8 bytes */ 7.29 + 7.30 + 7.31 typedef struct { 7.32 u32 cmd; /* EVTCHNOP_* */ /* 0 */ 7.33 u32 __reserved; /* 4 */ 7.34 @@ -154,6 +168,7 @@ typedef struct { 7.35 evtchn_close_t close; 7.36 evtchn_send_t send; 7.37 evtchn_status_t status; 7.38 + evtchn_bind_ipi_t bind_ipi; 7.39 u8 __dummy[24]; 7.40 } PACKED u; 7.41 } PACKED evtchn_op_t; /* 32 bytes */
8.1 --- a/xen/include/xen/sched.h Wed Nov 10 14:32:43 2004 +0000 8.2 +++ b/xen/include/xen/sched.h Wed Nov 10 15:43:53 2004 +0000 8.3 @@ -36,6 +36,7 @@ typedef struct event_channel_st 8.4 #define ECS_INTERDOMAIN 2 /* Channel is bound to another domain. */ 8.5 #define ECS_PIRQ 3 /* Channel is bound to a physical IRQ line. */ 8.6 #define ECS_VIRQ 4 /* Channel is bound to a virtual IRQ line. */ 8.7 +#define ECS_IPI 5 /* Channel is bound to a virtual IPI line. */ 8.8 u16 state; 8.9 union { 8.10 struct { 8.11 @@ -47,6 +48,7 @@ typedef struct event_channel_st 8.12 } __attribute__ ((packed)) interdomain; /* state == ECS_INTERDOMAIN */ 8.13 u16 pirq; /* state == ECS_PIRQ */ 8.14 u16 virq; /* state == ECS_VIRQ */ 8.15 + u32 ipi_edom; /* state == ECS_IPI */ 8.16 } u; 8.17 } event_channel_t; 8.18