mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Manual merge.
This commit is contained in:
commit
067bbfc35f
8 files changed
+135
-90
No files matched your search
@@ -1312,7 +1312,7 @@ void __devinit smp_prepare_boot_cpu(void)
|
||||
|
||||
/* hotplug down/up funtion pointer and target vcpu */
|
||||
struct vcpu_hotplug_handler_t {
|
||||
void (*fn)();
|
||||
void (*fn)(int vcpu);
|
||||
u32 vcpu;
|
||||
};
|
||||
static struct vcpu_hotplug_handler_t vcpu_hotplug_handler;
|
||||
@@ -1333,11 +1333,8 @@ static int __devinit cpu_enable(unsigned int cpu)
|
||||
while (!cpu_online(cpu))
|
||||
cpu_relax();
|
||||
|
||||
/* re-route bound IRQs 0 to cpu */
|
||||
rebind_evtchn_from_irq(0, cpu, per_cpu(resched_irq, cpu));
|
||||
rebind_evtchn_from_irq(0, cpu, per_cpu(callfunc_irq, cpu));
|
||||
|
||||
fixup_irqs(cpu_online_map);
|
||||
|
||||
/* counter the disable in fixup_irqs() */
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
@@ -1359,18 +1356,9 @@ int __cpu_disable(void)
|
||||
if (cpu == 0)
|
||||
return -EBUSY;
|
||||
|
||||
/* Allow any queued timer interrupts to get serviced */
|
||||
local_irq_enable();
|
||||
mdelay(1);
|
||||
local_irq_disable();
|
||||
|
||||
cpu_clear(cpu, map);
|
||||
fixup_irqs(map);
|
||||
|
||||
/* re-route IRQs from dead vcpu to another */
|
||||
rebind_evtchn_from_irq(cpu, 0, per_cpu(resched_irq, cpu));
|
||||
rebind_evtchn_from_irq(cpu, 0, per_cpu(callfunc_irq, cpu));
|
||||
|
||||
/* It's now safe to remove this processor from the online map */
|
||||
cpu_clear(cpu, cpu_online_map);
|
||||
|
||||
@@ -1533,13 +1521,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_on_cpu_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_on_cpu_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,
|
||||
|
||||
@@ -491,6 +491,8 @@ void ctrl_if_resume(void)
|
||||
* pick up its end of the event channel from
|
||||
*/
|
||||
evtchn_op_t op;
|
||||
extern void bind_evtchn_to_cpu(unsigned port, unsigned cpu);
|
||||
|
||||
op.cmd = EVTCHNOP_bind_interdomain;
|
||||
op.u.bind_interdomain.dom1 = DOMID_SELF;
|
||||
op.u.bind_interdomain.dom2 = DOMID_SELF;
|
||||
@@ -500,6 +502,7 @@ void ctrl_if_resume(void)
|
||||
BUG();
|
||||
xen_start_info.domain_controller_evtchn = op.u.bind_interdomain.port1;
|
||||
initdom_ctrlif_domcontroller_port = op.u.bind_interdomain.port2;
|
||||
bind_evtchn_to_cpu(op.u.bind_interdomain.port1, 0);
|
||||
}
|
||||
|
||||
/* Sync up with shared indexes. */
|
||||
|
||||
@@ -86,7 +86,7 @@ static u32 cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/32];
|
||||
cpu_evtchn_mask[cpu][idx] & \
|
||||
~(sh)->evtchn_mask[idx])
|
||||
|
||||
static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
|
||||
void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
|
||||
{
|
||||
clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
|
||||
set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
|
||||
@@ -99,8 +99,9 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
|
||||
((sh)->evtchn_pending[idx] & \
|
||||
~(sh)->evtchn_mask[idx])
|
||||
|
||||
#define bind_evtchn_to_cpu(chn,cpu) ((void)0)
|
||||
|
||||
void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Upcall to generic IRQ layer. */
|
||||
@@ -228,6 +229,13 @@ void unbind_virq_from_irq(int virq)
|
||||
if ( HYPERVISOR_event_channel_op(&op) != 0 )
|
||||
panic("Failed to unbind virtual IRQ %d\n", virq);
|
||||
|
||||
/* This is a slight hack. Interdomain ports can be allocated
|
||||
directly by userspace, and at that point they get bound by
|
||||
Xen to vcpu 0. We therefore need to make sure that if we
|
||||
get an event on an event channel we don't know about vcpu 0
|
||||
handles it. Binding channels to vcpu 0 when closing them
|
||||
achieves this. */
|
||||
bind_evtchn_to_cpu(evtchn, 0);
|
||||
evtchn_to_irq[evtchn] = -1;
|
||||
irq_to_evtchn[irq] = -1;
|
||||
per_cpu(virq_to_irq, cpu)[virq] = -1;
|
||||
@@ -236,17 +244,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;
|
||||
@@ -271,41 +279,10 @@ int bind_ipi_on_cpu_to_irq(int cpu, int ipi)
|
||||
return irq;
|
||||
}
|
||||
|
||||
void rebind_evtchn_from_ipi(int cpu, int newcpu, int ipi)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
|
||||
|
||||
spin_lock(&irq_mapping_update_lock);
|
||||
|
||||
op.cmd = EVTCHNOP_rebind;
|
||||
op.u.rebind.port = evtchn;
|
||||
op.u.rebind.vcpu = newcpu;
|
||||
if ( HYPERVISOR_event_channel_op(&op) != 0 )
|
||||
printk(KERN_INFO "Failed to rebind IPI%d to CPU%d\n",ipi,newcpu);
|
||||
|
||||
spin_unlock(&irq_mapping_update_lock);
|
||||
}
|
||||
|
||||
void rebind_evtchn_from_irq(int cpu, int newcpu, int irq)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
int evtchn = irq_to_evtchn[irq];
|
||||
|
||||
spin_lock(&irq_mapping_update_lock);
|
||||
|
||||
op.cmd = EVTCHNOP_rebind;
|
||||
op.u.rebind.port = evtchn;
|
||||
op.u.rebind.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];
|
||||
|
||||
@@ -319,6 +296,8 @@ void unbind_ipi_on_cpu_from_irq(int cpu, int ipi)
|
||||
if ( HYPERVISOR_event_channel_op(&op) != 0 )
|
||||
panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu);
|
||||
|
||||
/* See comments in unbind_virq_from_irq */
|
||||
bind_evtchn_to_cpu(evtchn, 0);
|
||||
evtchn_to_irq[evtchn] = -1;
|
||||
irq_to_evtchn[irq] = -1;
|
||||
per_cpu(ipi_to_evtchn, cpu)[ipi] = 0;
|
||||
@@ -362,6 +341,59 @@ void unbind_evtchn_from_irq(int evtchn)
|
||||
spin_unlock(&irq_mapping_update_lock);
|
||||
}
|
||||
|
||||
static void do_nothing_function(void *ign)
|
||||
{
|
||||
}
|
||||
|
||||
/* Rebind an evtchn so that it gets delivered to a specific cpu */
|
||||
static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
int evtchn;
|
||||
|
||||
spin_lock(&irq_mapping_update_lock);
|
||||
evtchn = irq_to_evtchn[irq];
|
||||
if (!VALID_EVTCHN(evtchn)) {
|
||||
spin_unlock(&irq_mapping_update_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tell Xen to send future instances of this interrupt to the
|
||||
other vcpu */
|
||||
op.cmd = EVTCHNOP_bind_vcpu;
|
||||
op.u.bind_vcpu.port = evtchn;
|
||||
op.u.bind_vcpu.vcpu = tcpu;
|
||||
|
||||
/* If this fails, it usually just indicates that we're dealing
|
||||
with a virq or IPI channel, which don't actually need to be
|
||||
rebound. Ignore it, but don't do the xenlinux-level rebind
|
||||
in that case. */
|
||||
if (HYPERVISOR_event_channel_op(&op) >= 0)
|
||||
bind_evtchn_to_cpu(evtchn, tcpu);
|
||||
|
||||
spin_unlock(&irq_mapping_update_lock);
|
||||
|
||||
/* Now send the new target processor a NOP IPI. When this
|
||||
returns, it will check for any pending interrupts, and so
|
||||
service any that got delivered to the wrong processor by
|
||||
mistake. */
|
||||
/* XXX: The only time this is called with interrupts disabled is
|
||||
from the hotplug/hotunplug path. In that case, all cpus are
|
||||
stopped with interrupts disabled, and the missed interrupts
|
||||
will be picked up when they start again. This is kind of a
|
||||
hack.
|
||||
*/
|
||||
if (!irqs_disabled()) {
|
||||
smp_call_function(do_nothing_function, NULL, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void set_affinity_irq(unsigned irq, cpumask_t dest)
|
||||
{
|
||||
unsigned tcpu = first_cpu(dest);
|
||||
rebind_irq_to_cpu(irq, tcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface to generic handling in irq.c
|
||||
@@ -424,7 +456,7 @@ static struct hw_interrupt_type dynirq_type = {
|
||||
disable_dynirq,
|
||||
ack_dynirq,
|
||||
end_dynirq,
|
||||
NULL
|
||||
set_affinity_irq
|
||||
};
|
||||
|
||||
static inline void pirq_unmask_notify(int pirq)
|
||||
@@ -473,6 +505,7 @@ static unsigned int startup_pirq(unsigned int irq)
|
||||
|
||||
pirq_query_unmask(irq_to_pirq(irq));
|
||||
|
||||
bind_evtchn_to_cpu(evtchn, 0);
|
||||
evtchn_to_irq[evtchn] = irq;
|
||||
irq_to_evtchn[irq] = evtchn;
|
||||
|
||||
@@ -498,6 +531,7 @@ static void shutdown_pirq(unsigned int irq)
|
||||
if ( HYPERVISOR_event_channel_op(&op) != 0 )
|
||||
panic("Failed to unbind physical IRQ %d\n", irq);
|
||||
|
||||
bind_evtchn_to_cpu(evtchn, 0);
|
||||
evtchn_to_irq[evtchn] = -1;
|
||||
irq_to_evtchn[irq] = -1;
|
||||
}
|
||||
@@ -548,7 +582,7 @@ static struct hw_interrupt_type pirq_type = {
|
||||
disable_pirq,
|
||||
ack_pirq,
|
||||
end_pirq,
|
||||
NULL
|
||||
set_affinity_irq
|
||||
};
|
||||
|
||||
void irq_suspend(void)
|
||||
@@ -597,6 +631,7 @@ void irq_resume(void)
|
||||
evtchn = op.u.bind_virq.port;
|
||||
|
||||
/* Record the new mapping. */
|
||||
bind_evtchn_to_cpu(evtchn, 0);
|
||||
evtchn_to_irq[evtchn] = irq;
|
||||
irq_to_evtchn[irq] = evtchn;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+30
-19
@@ -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,37 +565,55 @@ 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) ) {
|
||||
printf("vcpu %d bad.\n", vcpu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&d->evtchn_lock);
|
||||
|
||||
if ( !port_is_valid(d, port) )
|
||||
{
|
||||
printf("port %d bad.\n", port);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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:
|
||||
printf("evtchn type %d can't be rebound.\n", chn->state);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&d->evtchn_lock);
|
||||
@@ -664,10 +677,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:
|
||||
|
||||
@@ -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
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||