mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
xen/events: don't bind non-percpu VIRQs with percpu chip
commit 77bb3dfdc0d554befad58fdefbc41be5bc3ed38a upstream. A non-percpu VIRQ (e.g., VIRQ_CONSOLE) may be freed on a different VCPU than it is bound to. This can result in a race between handle_percpu_irq() and removing the action in __free_irq() because handle_percpu_irq() does not take desc->lock. The interrupt handler sees a NULL action and oopses. Only use the percpu chip/handler for per-CPU VIRQs (like VIRQ_TIMER). # cat /proc/interrupts | grep virq 40: 87246 0 xen-percpu-virq timer0 44: 0 0 xen-percpu-virq debug0 47: 0 20995 xen-percpu-virq timer1 51: 0 0 xen-percpu-virq debug1 69: 0 0 xen-dyn-virq xen-pcpu 74: 0 0 xen-dyn-virq mce 75: 29 0 xen-dyn-virq hvc_console Signed-off-by: David Vrabel <david.vrabel@citrix.com> [lizf: Backported to 3.4: adjust filename] Signed-off-by: Zefan Li <lizefan@huawei.com>
This commit is contained in:
parent
c1de4ad549
commit
0b80fa4b24
3 changed files with 10 additions and 6 deletions
|
@ -290,7 +290,7 @@ static int xen_initial_domain_console_init(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
|
||||
info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
|
||||
info->vtermno = HVC_COOKIE;
|
||||
|
||||
spin_lock(&xencons_lock);
|
||||
|
|
|
@ -906,7 +906,7 @@ static int find_virq(unsigned int virq, unsigned int cpu)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
|
||||
int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu)
|
||||
{
|
||||
struct evtchn_bind_virq bind_virq;
|
||||
int evtchn, irq, ret;
|
||||
|
@ -920,8 +920,12 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
|
|||
if (irq == -1)
|
||||
goto out;
|
||||
|
||||
irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
|
||||
handle_percpu_irq, "virq");
|
||||
if (percpu)
|
||||
irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
|
||||
handle_percpu_irq, "virq");
|
||||
else
|
||||
irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
|
||||
handle_edge_irq, "virq");
|
||||
|
||||
bind_virq.virq = virq;
|
||||
bind_virq.vcpu = cpu;
|
||||
|
@ -1042,7 +1046,7 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
|
|||
{
|
||||
int irq, retval;
|
||||
|
||||
irq = bind_virq_to_irq(virq, cpu);
|
||||
irq = bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
retval = request_irq(irq, handler, irqflags, devname, dev_id);
|
||||
|
|
|
@ -12,7 +12,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
|
|||
irq_handler_t handler,
|
||||
unsigned long irqflags, const char *devname,
|
||||
void *dev_id);
|
||||
int bind_virq_to_irq(unsigned int virq, unsigned int cpu);
|
||||
int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu);
|
||||
int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
|
||||
irq_handler_t handler,
|
||||
unsigned long irqflags, const char *devname,
|
||||
|
|
Loading…
Reference in a new issue