aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-07-08 14:17:54 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-07-08 14:17:54 +0000
commitc1a9064dc71e4d551043f4eb1646ea51c0ee572f (patch)
tree870a9c4af8ce8b0cb58cdb69f193de8e558ac950
parentacab4d6c5e1008a5337422e1b0a5d0e3e5ff9dc4 (diff)
downloadxen-c1a9064dc71e4d551043f4eb1646ea51c0ee572f.tar.gz
xen-c1a9064dc71e4d551043f4eb1646ea51c0ee572f.tar.bz2
xen-c1a9064dc71e4d551043f4eb1646ea51c0ee572f.zip
Clean up Xen's event-channel interface, and semantics for binding
to VCPUs. Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r--linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c4
-rw-r--r--linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c21
-rw-r--r--linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h4
-rw-r--r--linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h4
-rw-r--r--xen/common/event_channel.c45
-rw-r--r--xen/include/public/dom0_ops.h2
-rw-r--r--xen/include/public/event_channel.h26
7 files changed, 61 insertions, 45 deletions
diff --git a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
index 0a79ca6bcd..4798f1d4ec 100644
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
@@ -1533,13 +1533,13 @@ void __init smp_intr_init(void)
int cpu = smp_processor_id();
per_cpu(resched_irq, cpu) =
- bind_ipi_on_cpu_to_irq(cpu, RESCHEDULE_VECTOR);
+ bind_ipi_to_irq(RESCHEDULE_VECTOR);
sprintf(resched_name[cpu], "resched%d", cpu);
BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
SA_INTERRUPT, resched_name[cpu], NULL));
per_cpu(callfunc_irq, cpu) =
- bind_ipi_on_cpu_to_irq(cpu, CALL_FUNCTION_VECTOR);
+ bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
sprintf(callfunc_name[cpu], "callfunc%d", cpu);
BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
smp_call_function_interrupt,
diff --git a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c
index dda6c112e4..b293eee001 100644
--- a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c
+++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c
@@ -236,17 +236,17 @@ void unbind_virq_from_irq(int virq)
spin_unlock(&irq_mapping_update_lock);
}
-int bind_ipi_on_cpu_to_irq(int cpu, int ipi)
+int bind_ipi_on_cpu_to_irq(int ipi)
{
evtchn_op_t op;
int evtchn, irq;
+ int cpu = smp_processor_id();
spin_lock(&irq_mapping_update_lock);
if ( (evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0 )
{
- op.cmd = EVTCHNOP_bind_ipi;
- op.u.bind_ipi.ipi_vcpu = cpu;
+ op.cmd = EVTCHNOP_bind_ipi;
if ( HYPERVISOR_event_channel_op(&op) != 0 )
panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu);
evtchn = op.u.bind_ipi.port;
@@ -278,9 +278,9 @@ void rebind_evtchn_from_ipi(int cpu, int newcpu, int ipi)
spin_lock(&irq_mapping_update_lock);
- op.cmd = EVTCHNOP_rebind;
- op.u.rebind.port = evtchn;
- op.u.rebind.vcpu = newcpu;
+ op.cmd = EVTCHNOP_bind_vcpu;
+ op.u.bind_vcpu.port = evtchn;
+ op.u.bind_vcpu.vcpu = newcpu;
if ( HYPERVISOR_event_channel_op(&op) != 0 )
printk(KERN_INFO "Failed to rebind IPI%d to CPU%d\n",ipi,newcpu);
@@ -294,18 +294,19 @@ void rebind_evtchn_from_irq(int cpu, int newcpu, int irq)
spin_lock(&irq_mapping_update_lock);
- op.cmd = EVTCHNOP_rebind;
- op.u.rebind.port = evtchn;
- op.u.rebind.vcpu = newcpu;
+ op.cmd = EVTCHNOP_bind_vcpu;
+ op.u.bind_vcpu.port = evtchn;
+ op.u.bind_vcpu.vcpu = newcpu;
if ( HYPERVISOR_event_channel_op(&op) != 0 )
printk(KERN_INFO "Failed to rebind IRQ%d to CPU%d\n",irq,newcpu);
spin_unlock(&irq_mapping_update_lock);
}
-void unbind_ipi_on_cpu_from_irq(int cpu, int ipi)
+void unbind_ipi_from_irq(int ipi)
{
evtchn_op_t op;
+ int cpu = smp_processor_id();
int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
int irq = irq_to_evtchn[evtchn];
diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
index 88c5faaf84..af4ed763fa 100644
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
@@ -128,8 +128,8 @@
/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
extern int bind_virq_to_irq(int virq);
extern void unbind_virq_from_irq(int virq);
-extern int bind_ipi_on_cpu_to_irq(int cpu, int ipi);
-extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
+extern int bind_ipi_to_irq(int ipi);
+extern void unbind_ipi_from_irq(int ipi);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
index 8f19c41675..f72c14da1f 100644
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
@@ -126,8 +126,8 @@
/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
extern int bind_virq_to_irq(int virq);
extern void unbind_virq_from_irq(int virq);
-extern int bind_ipi_on_cpu_to_irq(int cpu, int ipi);
-extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
+extern int bind_ipi_to_irq(int ipi);
+extern void unbind_ipi_from_irq(int ipi);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 61ad635f5e..13145e114d 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -220,12 +220,10 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
chn1->u.interdomain.remote_dom = d2;
chn1->u.interdomain.remote_port = (u16)port2;
- chn1->notify_vcpu_id = 0;
chn1->state = ECS_INTERDOMAIN;
chn2->u.interdomain.remote_dom = d1;
chn2->u.interdomain.remote_port = (u16)port1;
- chn2->notify_vcpu_id = 0;
chn2->state = ECS_INTERDOMAIN;
out:
@@ -285,10 +283,7 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
{
struct evtchn *chn;
struct domain *d = current->domain;
- int port, ipi_vcpu = bind->ipi_vcpu;
-
- if ( (ipi_vcpu >= MAX_VIRT_CPUS) || (d->vcpu[ipi_vcpu] == NULL) )
- return -EINVAL;
+ int port;
spin_lock(&d->evtchn_lock);
@@ -296,7 +291,7 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
{
chn = evtchn_from_port(d, port);
chn->state = ECS_IPI;
- chn->notify_vcpu_id = ipi_vcpu;
+ chn->notify_vcpu_id = current->vcpu_id;
}
spin_unlock(&d->evtchn_lock);
@@ -326,8 +321,6 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
chn = evtchn_from_port(d, port);
- chn->notify_vcpu_id = 0;
-
d->pirq_to_evtchn[pirq] = port;
rc = pirq_guest_bind(d->vcpu[0], pirq,
!!(bind->flags & BIND_PIRQ__WILL_SHARE));
@@ -441,7 +434,9 @@ static long __evtchn_close(struct domain *d1, int port1)
BUG();
}
- chn1->state = ECS_FREE;
+ /* Reset binding to vcpu0 when the channel is freed. */
+ chn1->state = ECS_FREE;
+ chn1->notify_vcpu_id = 0;
out:
if ( d2 != NULL )
@@ -570,26 +565,30 @@ static long evtchn_status(evtchn_status_t *status)
status->u.virq = chn->u.virq;
break;
case ECS_IPI:
- status->status = EVTCHNSTAT_ipi;
- status->u.ipi_vcpu = chn->notify_vcpu_id;
+ status->status = EVTCHNSTAT_ipi;
break;
default:
BUG();
}
+ status->vcpu = chn->notify_vcpu_id;
+
out:
spin_unlock(&d->evtchn_lock);
put_domain(d);
return rc;
}
-static long evtchn_rebind(evtchn_rebind_t *bind)
+static long evtchn_bind_vcpu(evtchn_bind_vcpu_t *bind)
{
struct domain *d = current->domain;
int port = bind->port;
int vcpu = bind->vcpu;
struct evtchn *chn;
- long rc = 0;
+ long rc = 0;
+
+ if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) )
+ return -EINVAL;
spin_lock(&d->evtchn_lock);
@@ -600,7 +599,17 @@ static long evtchn_rebind(evtchn_rebind_t *bind)
}
chn = evtchn_from_port(d, port);
- chn->notify_vcpu_id = vcpu;
+ switch ( chn->state )
+ {
+ case ECS_UNBOUND:
+ case ECS_INTERDOMAIN:
+ case ECS_PIRQ:
+ chn->notify_vcpu_id = vcpu;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
out:
spin_unlock(&d->evtchn_lock);
@@ -664,10 +673,8 @@ long do_event_channel_op(evtchn_op_t *uop)
rc = -EFAULT;
break;
- case EVTCHNOP_rebind:
- rc = evtchn_rebind(&op.u.rebind);
- if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
- rc = -EFAULT;
+ case EVTCHNOP_bind_vcpu:
+ rc = evtchn_bind_vcpu(&op.u.bind_vcpu);
break;
default:
diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h
index 60e215b09c..2502edd75a 100644
--- a/xen/include/public/dom0_ops.h
+++ b/xen/include/public/dom0_ops.h
@@ -19,7 +19,7 @@
* This makes sure that old versions of dom0 tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define DOM0_INTERFACE_VERSION 0xAAAA100D
+#define DOM0_INTERFACE_VERSION 0xAAAA100E
/************************************************************************/
diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h
index ceacf3fc34..d1629ec244 100644
--- a/xen/include/public/event_channel.h
+++ b/xen/include/public/event_channel.h
@@ -89,8 +89,6 @@ typedef struct evtchn_bind_pirq {
*/
#define EVTCHNOP_bind_ipi 7
typedef struct evtchn_bind_ipi {
- /* IN parameters. */
- u32 ipi_vcpu;
/* OUT parameters. */
u32 port;
} evtchn_bind_ipi_t;
@@ -144,6 +142,7 @@ typedef struct evtchn_status {
#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
u32 status;
+ u32 vcpu; /* VCPU to which this channel is bound. */
union {
struct {
domid_t dom;
@@ -154,16 +153,25 @@ typedef struct evtchn_status {
} interdomain; /* EVTCHNSTAT_interdomain */
u32 pirq; /* EVTCHNSTAT_pirq */
u32 virq; /* EVTCHNSTAT_virq */
- u32 ipi_vcpu; /* EVTCHNSTAT_ipi */
} u;
} evtchn_status_t;
-#define EVTCHNOP_rebind 8
-typedef struct {
+/*
+ * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
+ * event is pending.
+ * NOTES:
+ * 1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
+ * the binding. This binding cannot be changed.
+ * 2. All other channels notify vcpu0 by default. This default is set when
+ * the channel is allocated (a port that is freed and subsequently reused
+ * has its binding reset to vcpu0).
+ */
+#define EVTCHNOP_bind_vcpu 8
+typedef struct evtchn_bind_vcpu {
/* IN parameters. */
- u32 port; /* 0 */
- u32 vcpu; /* 4 */
-} evtchn_rebind_t; /* 8 bytes */
+ u32 port;
+ u32 vcpu;
+} evtchn_bind_vcpu_t;
typedef struct evtchn_op {
u32 cmd; /* EVTCHNOP_* */
@@ -176,7 +184,7 @@ typedef struct evtchn_op {
evtchn_close_t close;
evtchn_send_t send;
evtchn_status_t status;
- evtchn_rebind_t rebind;
+ evtchn_bind_vcpu_t bind_vcpu;
} u;
} evtchn_op_t;