]>
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 | ||
23 | Index: linux-2.6.26/arch/x86/kernel/apic_64.c | |
24 | =================================================================== | |
25 | --- linux-2.6.26.orig/arch/x86/kernel/apic_64.c | |
26 | +++ linux-2.6.26/arch/x86/kernel/apic_64.c | |
27 | @@ -969,7 +969,12 @@ void enable_IR_x2apic(void) | |
28 | ||
29 | local_irq_save(flags); | |
30 | mask_8259A(); | |
31 | - save_mask_IO_APIC_setup(); | |
32 | + | |
33 | + ret = save_mask_IO_APIC_setup(); | |
34 | + if (ret) { | |
35 | + printk(KERN_INFO "Saving IO-APIC state failed: %d\n", ret); | |
36 | + goto end; | |
37 | + } | |
38 | ||
39 | ret = enable_intr_remapping(1); | |
40 | ||
41 | @@ -979,14 +984,15 @@ void enable_IR_x2apic(void) | |
42 | } | |
43 | ||
44 | if (ret) | |
45 | - goto end; | |
46 | + goto end_restore; | |
47 | ||
48 | if (!x2apic) { | |
49 | x2apic = 1; | |
50 | apic_ops = &x2apic_ops; | |
51 | enable_x2apic(); | |
52 | } | |
53 | -end: | |
54 | + | |
55 | + end_restore: | |
56 | if (ret) | |
57 | /* | |
58 | * IR enabling failed | |
59 | @@ -995,6 +1001,7 @@ end: | |
60 | else | |
61 | reinit_intr_remapped_IO_APIC(x2apic_preenabled); | |
62 | ||
63 | + end: | |
64 | unmask_8259A(); | |
65 | local_irq_restore(flags); | |
66 | ||
67 | Index: linux-2.6.26/arch/x86/kernel/io_apic_64.c | |
68 | =================================================================== | |
69 | --- linux-2.6.26.orig/arch/x86/kernel/io_apic_64.c | |
70 | +++ linux-2.6.26/arch/x86/kernel/io_apic_64.c | |
71 | @@ -474,7 +474,7 @@ int save_mask_IO_APIC_setup(void) | |
72 | kzalloc(sizeof(struct IO_APIC_route_entry) * | |
73 | nr_ioapic_registers[apic], GFP_KERNEL); | |
74 | if (!early_ioapic_entries[apic]) | |
75 | - return -ENOMEM; | |
76 | + goto nomem; | |
77 | } | |
78 | ||
79 | for (apic = 0; apic < nr_ioapics; apic++) | |
80 | @@ -489,16 +489,31 @@ int save_mask_IO_APIC_setup(void) | |
81 | } | |
82 | } | |
83 | return 0; | |
84 | + | |
85 | + nomem: | |
86 | + for (; apic > 0; apic--) | |
87 | + kfree(early_ioapic_entries[apic]); | |
88 | + kfree(early_ioapic_entries[apic]); | |
89 | + memset(early_ioapic_entries, 0, | |
90 | + ARRAY_SIZE(early_ioapic_entries)); | |
91 | + | |
92 | + return -ENOMEM; | |
93 | + | |
94 | } | |
95 | ||
96 | void restore_IO_APIC_setup(void) | |
97 | { | |
98 | int apic, pin; | |
99 | ||
100 | - for (apic = 0; apic < nr_ioapics; apic++) | |
101 | + for (apic = 0; apic < nr_ioapics; apic++) { | |
102 | + if (!early_ioapic_entries[apic]) | |
103 | + break; | |
104 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | |
105 | ioapic_write_entry(apic, pin, | |
106 | early_ioapic_entries[apic][pin]); | |
107 | + kfree(early_ioapic_entries[apic]); | |
108 | + early_ioapic_entries[apic] = NULL; | |
109 | + } | |
110 | } | |
111 | ||
112 | void reinit_intr_remapped_IO_APIC(int intr_remapping) |