Skip to content

Commit

Permalink
xen-evtchn: Bind dyn evtchn:qemu-dm interrupt to next online VCPU
Browse files Browse the repository at this point in the history
A HVM domian booting generates around 200K (evtchn:qemu-dm xen-dyn)
interrupts,in a short period of time. All these evtchn:qemu-dm are bound
to VCPU 0, until irqbalance sees these IRQ and moves it to a different VCPU.
In one configuration, irqbalance runs every 10 seconds, which means
irqbalance doesn't get to see these burst of interrupts and doesn't
re-balance interrupts most of the time, making all evtchn:qemu-dm to be
processed by VCPU0. This cause VCPU0 to spend most of time processing
hardirq and very little time on softirq. Moreover, if dom0 kernel PREEMPTION
is disabled, VCPU0 never runs watchdog (process context), triggering a
softlockup detection code to panic.

Binding evtchn:qemu-dm to next online VCPU, will spread hardirq
processing evenly across different CPU. Later, irqbalance will try to balance
evtchn:qemu-dm, if required.

Signed-off-by: Anoob Soman <[email protected]>
Reviewed-by: Boris Ostrovsky <[email protected]>
Signed-off-by: Juergen Gross <[email protected]>
  • Loading branch information
anoobs authored and jgross1 committed Jun 13, 2017
1 parent 9cc91f2 commit c48f64a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
6 changes: 3 additions & 3 deletions drivers/xen/events/events_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1303,10 +1303,9 @@ void rebind_evtchn_irq(int evtchn, int irq)
}

/* Rebind an evtchn so that it gets delivered to a specific cpu */
static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
int xen_rebind_evtchn_to_cpu(int evtchn, unsigned tcpu)
{
struct evtchn_bind_vcpu bind_vcpu;
int evtchn = evtchn_from_irq(irq);
int masked;

if (!VALID_EVTCHN(evtchn))
Expand Down Expand Up @@ -1338,13 +1337,14 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)

return 0;
}
EXPORT_SYMBOL_GPL(xen_rebind_evtchn_to_cpu);

static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
bool force)
{
unsigned tcpu = cpumask_first_and(dest, cpu_online_mask);

return rebind_irq_to_cpu(data->irq, tcpu);
return xen_rebind_evtchn_to_cpu(evtchn_from_irq(data->irq), tcpu);
}

static void enable_dynirq(struct irq_data *data)
Expand Down
34 changes: 33 additions & 1 deletion drivers/xen/evtchn.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,36 @@ static void evtchn_unbind_from_user(struct per_user_data *u,
del_evtchn(u, evtchn);
}

static DEFINE_PER_CPU(int, bind_last_selected_cpu);

static void evtchn_bind_interdom_next_vcpu(int evtchn)
{
unsigned int selected_cpu, irq;
struct irq_desc *desc;
unsigned long flags;

irq = irq_from_evtchn(evtchn);
desc = irq_to_desc(irq);

if (!desc)
return;

raw_spin_lock_irqsave(&desc->lock, flags);
selected_cpu = this_cpu_read(bind_last_selected_cpu);
selected_cpu = cpumask_next_and(selected_cpu,
desc->irq_common_data.affinity, cpu_online_mask);

if (unlikely(selected_cpu >= nr_cpu_ids))
selected_cpu = cpumask_first_and(desc->irq_common_data.affinity,
cpu_online_mask);

this_cpu_write(bind_last_selected_cpu, selected_cpu);

/* unmask expects irqs to be disabled */
xen_rebind_evtchn_to_cpu(evtchn, selected_cpu);
raw_spin_unlock_irqrestore(&desc->lock, flags);
}

static long evtchn_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
Expand Down Expand Up @@ -478,8 +508,10 @@ static long evtchn_ioctl(struct file *file,
break;

rc = evtchn_bind_to_user(u, bind_interdomain.local_port);
if (rc == 0)
if (rc == 0) {
rc = bind_interdomain.local_port;
evtchn_bind_interdom_next_vcpu(rc);
}
break;
}

Expand Down
1 change: 1 addition & 0 deletions include/xen/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ void evtchn_put(unsigned int evtchn);

void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
void rebind_evtchn_irq(int evtchn, int irq);
int xen_rebind_evtchn_to_cpu(int evtchn, unsigned tcpu);

static inline void notify_remote_via_evtchn(int port)
{
Expand Down

0 comments on commit c48f64a

Please sign in to comment.