]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Cyrill Gorcunov <gorcunov@gmail.com> |
2 | Subject: x86: io-apic - interrupt remapping fix | |
3 | References: fate #303948 and fate #303984 | |
4 | Patch-Mainline: queued for .28 | |
5 | Commit-ID: 77322deb4bc676a5ee645444e7ed1a89f854473d | |
6 | ||
7 | Signed-off-by: Thomas Renninger <trenn@suse.de> | |
8 | ||
9 | Interrupt remapping could lead to NULL dereference in case of | |
10 | kzalloc failed and memory leak in other way. So fix the | |
11 | both cases. | |
12 | ||
13 | Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com> | |
14 | Cc: "Maciej W. Rozycki" <macro@linux-mips.org> | |
15 | Cc: Suresh Siddha <suresh.b.siddha@intel.com> | |
16 | Signed-off-by: Ingo Molnar <mingo@elte.hu> | |
17 | ||
18 | --- | |
19 | arch/x86/kernel/apic_64.c | 13 ++++++++++--- | |
20 | arch/x86/kernel/io_apic_64.c | 19 +++++++++++++++++-- | |
21 | 2 files changed, 27 insertions(+), 5 deletions(-) | |
22 | ||
82094b55 AF |
23 | --- a/arch/x86/kernel/apic_64.c |
24 | +++ b/arch/x86/kernel/apic_64.c | |
25 | @@ -996,7 +996,12 @@ void enable_IR_x2apic(void) | |
2cb7cef9 BS |
26 | |
27 | local_irq_save(flags); | |
28 | mask_8259A(); | |
29 | - save_mask_IO_APIC_setup(); | |
30 | + | |
31 | + ret = save_mask_IO_APIC_setup(); | |
32 | + if (ret) { | |
33 | + printk(KERN_INFO "Saving IO-APIC state failed: %d\n", ret); | |
34 | + goto end; | |
35 | + } | |
36 | ||
37 | ret = enable_intr_remapping(1); | |
38 | ||
82094b55 | 39 | @@ -1006,14 +1011,15 @@ void enable_IR_x2apic(void) |
2cb7cef9 BS |
40 | } |
41 | ||
42 | if (ret) | |
43 | - goto end; | |
44 | + goto end_restore; | |
45 | ||
46 | if (!x2apic) { | |
47 | x2apic = 1; | |
48 | apic_ops = &x2apic_ops; | |
49 | enable_x2apic(); | |
50 | } | |
51 | -end: | |
52 | + | |
53 | + end_restore: | |
54 | if (ret) | |
55 | /* | |
56 | * IR enabling failed | |
82094b55 | 57 | @@ -1022,6 +1028,7 @@ end: |
2cb7cef9 BS |
58 | else |
59 | reinit_intr_remapped_IO_APIC(x2apic_preenabled); | |
60 | ||
61 | + end: | |
62 | unmask_8259A(); | |
63 | local_irq_restore(flags); | |
64 | ||
82094b55 AF |
65 | --- a/arch/x86/kernel/io_apic_64.c |
66 | +++ b/arch/x86/kernel/io_apic_64.c | |
2cb7cef9 BS |
67 | @@ -474,7 +474,7 @@ int save_mask_IO_APIC_setup(void) |
68 | kzalloc(sizeof(struct IO_APIC_route_entry) * | |
69 | nr_ioapic_registers[apic], GFP_KERNEL); | |
70 | if (!early_ioapic_entries[apic]) | |
71 | - return -ENOMEM; | |
72 | + goto nomem; | |
73 | } | |
74 | ||
75 | for (apic = 0; apic < nr_ioapics; apic++) | |
76 | @@ -489,16 +489,31 @@ int save_mask_IO_APIC_setup(void) | |
77 | } | |
78 | } | |
79 | return 0; | |
80 | + | |
81 | + nomem: | |
82 | + for (; apic > 0; apic--) | |
83 | + kfree(early_ioapic_entries[apic]); | |
84 | + kfree(early_ioapic_entries[apic]); | |
85 | + memset(early_ioapic_entries, 0, | |
86 | + ARRAY_SIZE(early_ioapic_entries)); | |
87 | + | |
88 | + return -ENOMEM; | |
89 | + | |
90 | } | |
91 | ||
92 | void restore_IO_APIC_setup(void) | |
93 | { | |
94 | int apic, pin; | |
95 | ||
96 | - for (apic = 0; apic < nr_ioapics; apic++) | |
97 | + for (apic = 0; apic < nr_ioapics; apic++) { | |
98 | + if (!early_ioapic_entries[apic]) | |
99 | + break; | |
100 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | |
101 | ioapic_write_entry(apic, pin, | |
102 | early_ioapic_entries[apic][pin]); | |
103 | + kfree(early_ioapic_entries[apic]); | |
104 | + early_ioapic_entries[apic] = NULL; | |
105 | + } | |
106 | } | |
107 | ||
108 | void reinit_intr_remapped_IO_APIC(int intr_remapping) |