]>
Commit | Line | Data |
---|---|---|
b91494dd GKH |
1 | From 8ed8ab40047a570fdd8043a40c104a57248dd3fd Mon Sep 17 00:00:00 2001 |
2 | From: Hari Bathini <hbathini@linux.vnet.ibm.com> | |
3 | Date: Fri, 15 Apr 2016 22:48:02 +1000 | |
4 | Subject: powerpc/book3s64: Fix branching to OOL handlers in relocatable kernel | |
5 | ||
6 | From: Hari Bathini <hbathini@linux.vnet.ibm.com> | |
7 | ||
8 | commit 8ed8ab40047a570fdd8043a40c104a57248dd3fd upstream. | |
9 | ||
10 | Some of the interrupt vectors on 64-bit POWER server processors are only | |
11 | 32 bytes long (8 instructions), which is not enough for the full | |
12 | first-level interrupt handler. For these we need to branch to an | |
13 | out-of-line (OOL) handler. But when we are running a relocatable kernel, | |
14 | interrupt vectors till __end_interrupts marker are copied down to real | |
15 | address 0x100. So, branching to labels (ie. OOL handlers) outside this | |
16 | section must be handled differently (see LOAD_HANDLER()), considering | |
17 | relocatable kernel, which would need at least 4 instructions. | |
18 | ||
19 | However, branching from interrupt vector means that we corrupt the | |
20 | CFAR (come-from address register) on POWER7 and later processors as | |
21 | mentioned in commit 1707dd16. So, EXCEPTION_PROLOG_0 (6 instructions) | |
22 | that contains the part up to the point where the CFAR is saved in the | |
23 | PACA should be part of the short interrupt vectors before we branch out | |
24 | to OOL handlers. | |
25 | ||
26 | But as mentioned already, there are interrupt vectors on 64-bit POWER | |
27 | server processors that are only 32 bytes long (like vectors 0x4f00, | |
28 | 0x4f20, etc.), which cannot accomodate the above two cases at the same | |
29 | time owing to space constraint. Currently, in these interrupt vectors, | |
30 | we simply branch out to OOL handlers, without using LOAD_HANDLER(), | |
31 | which leaves us vulnerable when running a relocatable kernel (eg. kdump | |
32 | case). While this has been the case for sometime now and kdump is used | |
33 | widely, we were fortunate not to see any problems so far, for three | |
34 | reasons: | |
35 | ||
36 | 1. In almost all cases, production kernel (relocatable) is used for | |
37 | kdump as well, which would mean that crashed kernel's OOL handler | |
38 | would be at the same place where we end up branching to, from short | |
39 | interrupt vector of kdump kernel. | |
40 | 2. Also, OOL handler was unlikely the reason for crash in almost all | |
41 | the kdump scenarios, which meant we had a sane OOL handler from | |
42 | crashed kernel that we branched to. | |
43 | 3. On most 64-bit POWER server processors, page size is large enough | |
44 | that marking interrupt vector code as executable (see commit | |
45 | 429d2e83) leads to marking OOL handler code from crashed kernel, | |
46 | that sits right below interrupt vector code from kdump kernel, as | |
47 | executable as well. | |
48 | ||
49 | Let us fix this by moving the __end_interrupts marker down past OOL | |
50 | handlers to make sure that we also copy OOL handlers to real address | |
51 | 0x100 when running a relocatable kernel. | |
52 | ||
53 | This fix has been tested successfully in kdump scenario, on an LPAR with | |
54 | 4K page size by using different default/production kernel and kdump | |
55 | kernel. | |
56 | ||
57 | Also tested by manually corrupting the OOL handlers in the first kernel | |
58 | and then kdump'ing, and then causing the OOL handlers to fire - mpe. | |
59 | ||
60 | Fixes: c1fb6816fb1b ("powerpc: Add relocation on exception vector handlers") | |
61 | Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com> | |
62 | Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> | |
63 | Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> | |
64 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
65 | ||
66 | --- | |
67 | arch/powerpc/kernel/exceptions-64s.S | 16 +++++++++++----- | |
68 | 1 file changed, 11 insertions(+), 5 deletions(-) | |
69 | ||
70 | --- a/arch/powerpc/kernel/exceptions-64s.S | |
71 | +++ b/arch/powerpc/kernel/exceptions-64s.S | |
72 | @@ -962,11 +962,6 @@ hv_facility_unavailable_relon_trampoline | |
73 | #endif | |
74 | STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist) | |
75 | ||
76 | - /* Other future vectors */ | |
77 | - .align 7 | |
78 | - .globl __end_interrupts | |
79 | -__end_interrupts: | |
80 | - | |
81 | .align 7 | |
82 | system_call_entry: | |
83 | b system_call_common | |
84 | @@ -1253,6 +1248,17 @@ __end_handlers: | |
85 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable) | |
86 | STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable) | |
87 | ||
88 | + /* | |
89 | + * The __end_interrupts marker must be past the out-of-line (OOL) | |
90 | + * handlers, so that they are copied to real address 0x100 when running | |
91 | + * a relocatable kernel. This ensures they can be reached from the short | |
92 | + * trampoline handlers (like 0x4f00, 0x4f20, etc.) which branch | |
93 | + * directly, without using LOAD_HANDLER(). | |
94 | + */ | |
95 | + .align 7 | |
96 | + .globl __end_interrupts | |
97 | +__end_interrupts: | |
98 | + | |
99 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | |
100 | /* | |
101 | * Data area reserved for FWNMI option. |