]>
Commit | Line | Data |
---|---|---|
b91494dd GKH |
1 | From f0f393877c71ad227d36705d61d1e4062bc29cf5 Mon Sep 17 00:00:00 2001 |
2 | From: Ross Lagerwall <ross.lagerwall@citrix.com> | |
3 | Date: Tue, 10 May 2016 16:11:00 +0100 | |
4 | Subject: xen/events: Don't move disabled irqs | |
5 | ||
6 | From: Ross Lagerwall <ross.lagerwall@citrix.com> | |
7 | ||
8 | commit f0f393877c71ad227d36705d61d1e4062bc29cf5 upstream. | |
9 | ||
10 | Commit ff1e22e7a638 ("xen/events: Mask a moving irq") open-coded | |
11 | irq_move_irq() but left out checking if the IRQ is disabled. This broke | |
12 | resuming from suspend since it tries to move a (disabled) irq without | |
13 | holding the IRQ's desc->lock. Fix it by adding in a check for disabled | |
14 | IRQs. | |
15 | ||
16 | The resulting stacktrace was: | |
17 | kernel BUG at /build/linux-UbQGH5/linux-4.4.0/kernel/irq/migration.c:31! | |
18 | invalid opcode: 0000 [#1] SMP | |
19 | Modules linked in: xenfs xen_privcmd ... | |
20 | CPU: 0 PID: 9 Comm: migration/0 Not tainted 4.4.0-22-generic #39-Ubuntu | |
21 | Hardware name: Xen HVM domU, BIOS 4.6.1-xs125180 05/04/2016 | |
22 | task: ffff88003d75ee00 ti: ffff88003d7bc000 task.ti: ffff88003d7bc000 | |
23 | RIP: 0010:[<ffffffff810e26e2>] [<ffffffff810e26e2>] irq_move_masked_irq+0xd2/0xe0 | |
24 | RSP: 0018:ffff88003d7bfc50 EFLAGS: 00010046 | |
25 | RAX: 0000000000000000 RBX: ffff88003d40ba00 RCX: 0000000000000001 | |
26 | RDX: 0000000000000001 RSI: 0000000000000100 RDI: ffff88003d40bad8 | |
27 | RBP: ffff88003d7bfc68 R08: 0000000000000000 R09: ffff88003d000000 | |
28 | R10: 0000000000000000 R11: 000000000000023c R12: ffff88003d40bad0 | |
29 | R13: ffffffff81f3a4a0 R14: 0000000000000010 R15: 00000000ffffffff | |
30 | FS: 0000000000000000(0000) GS:ffff88003da00000(0000) knlGS:0000000000000000 | |
31 | CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | |
32 | CR2: 00007fd4264de624 CR3: 0000000037922000 CR4: 00000000003406f0 | |
33 | DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 | |
34 | DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 | |
35 | Stack: | |
36 | ffff88003d40ba38 0000000000000024 0000000000000000 ffff88003d7bfca0 | |
37 | ffffffff814c8d92 00000010813ef89d 00000000805ea732 0000000000000009 | |
38 | 0000000000000024 ffff88003cc39b80 ffff88003d7bfce0 ffffffff814c8f66 | |
39 | Call Trace: | |
40 | [<ffffffff814c8d92>] eoi_pirq+0xb2/0xf0 | |
41 | [<ffffffff814c8f66>] __startup_pirq+0xe6/0x150 | |
42 | [<ffffffff814ca659>] xen_irq_resume+0x319/0x360 | |
43 | [<ffffffff814c7e75>] xen_suspend+0xb5/0x180 | |
44 | [<ffffffff81120155>] multi_cpu_stop+0xb5/0xe0 | |
45 | [<ffffffff811200a0>] ? cpu_stop_queue_work+0x80/0x80 | |
46 | [<ffffffff811203d0>] cpu_stopper_thread+0xb0/0x140 | |
47 | [<ffffffff810a94e6>] ? finish_task_switch+0x76/0x220 | |
48 | [<ffffffff810ca731>] ? __raw_callee_save___pv_queued_spin_unlock+0x11/0x20 | |
49 | [<ffffffff810a3935>] smpboot_thread_fn+0x105/0x160 | |
50 | [<ffffffff810a3830>] ? sort_range+0x30/0x30 | |
51 | [<ffffffff810a0588>] kthread+0xd8/0xf0 | |
52 | [<ffffffff810a04b0>] ? kthread_create_on_node+0x1e0/0x1e0 | |
53 | [<ffffffff8182568f>] ret_from_fork+0x3f/0x70 | |
54 | [<ffffffff810a04b0>] ? kthread_create_on_node+0x1e0/0x1e0 | |
55 | ||
56 | Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com> | |
57 | Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> | |
58 | Signed-off-by: David Vrabel <david.vrabel@citrix.com> | |
59 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
60 | ||
61 | --- | |
62 | drivers/xen/events/events_base.c | 6 ++++-- | |
63 | 1 file changed, 4 insertions(+), 2 deletions(-) | |
64 | ||
65 | --- a/drivers/xen/events/events_base.c | |
66 | +++ b/drivers/xen/events/events_base.c | |
67 | @@ -487,7 +487,8 @@ static void eoi_pirq(struct irq_data *da | |
68 | if (!VALID_EVTCHN(evtchn)) | |
69 | return; | |
70 | ||
71 | - if (unlikely(irqd_is_setaffinity_pending(data))) { | |
72 | + if (unlikely(irqd_is_setaffinity_pending(data)) && | |
73 | + likely(!irqd_irq_disabled(data))) { | |
74 | int masked = test_and_set_mask(evtchn); | |
75 | ||
76 | clear_evtchn(evtchn); | |
77 | @@ -1370,7 +1371,8 @@ static void ack_dynirq(struct irq_data * | |
78 | if (!VALID_EVTCHN(evtchn)) | |
79 | return; | |
80 | ||
81 | - if (unlikely(irqd_is_setaffinity_pending(data))) { | |
82 | + if (unlikely(irqd_is_setaffinity_pending(data)) && | |
83 | + likely(!irqd_irq_disabled(data))) { | |
84 | int masked = test_and_set_mask(evtchn); | |
85 | ||
86 | clear_evtchn(evtchn); |