Manual merge.

This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-07-09 10:24:14 +00:00
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
View File
@@ -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:
+1 -1
View File
@@ -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
/************************************************************************/
+17 -9
View File
@@ -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;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.