]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.14.16/xtensa-add-fixup-for-double-exception-raised-in-window-overflow.patch
drop queue-4.14/mips-make-sure-dt-memory-regions-are-valid.patch
[thirdparty/kernel/stable-queue.git] / releases / 3.14.16 / xtensa-add-fixup-for-double-exception-raised-in-window-overflow.patch
1 From 17290231df16eeee5dfc198dbf5ee4b419996dcd Mon Sep 17 00:00:00 2001
2 From: Max Filippov <jcmvbkbc@gmail.com>
3 Date: Sat, 24 May 2014 21:48:28 +0400
4 Subject: xtensa: add fixup for double exception raised in window overflow
5
6 From: Max Filippov <jcmvbkbc@gmail.com>
7
8 commit 17290231df16eeee5dfc198dbf5ee4b419996dcd upstream.
9
10 There are two FIXMEs in the double exception handler 'for the extremely
11 unlikely case'. This case gets hit by gcc during kernel build once in
12 a few hours, resulting in an unrecoverable exception condition.
13
14 Provide missing fixup routine to handle this case. Double exception
15 literals now need 8 more bytes, add them to the linker script.
16
17 Also replace bbsi instructions with bbsi.l as we're branching depending
18 on 8th and 7th LSB-based bits of exception address.
19
20 This may be tested by adding the explicit DTLB invalidation to window
21 overflow handlers, like the following:
22
23 # --- a/arch/xtensa/kernel/vectors.S
24 # +++ b/arch/xtensa/kernel/vectors.S
25 # @@ -592,6 +592,14 @@ ENDPROC(_WindowUnderflow4)
26 # ENTRY_ALIGN64(_WindowOverflow8)
27 #
28 # s32e a0, a9, -16
29 # + bbsi.l a9, 31, 1f
30 # + rsr a0, ccount
31 # + bbsi.l a0, 4, 1f
32 # + pdtlb a0, a9
33 # + idtlb a0
34 # + movi a0, 9
35 # + idtlb a0
36 # +1:
37 # l32e a0, a1, -12
38 # s32e a2, a9, -8
39 # s32e a1, a9, -12
40
41 Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
42 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
43
44 ---
45 arch/xtensa/kernel/vectors.S | 158 +++++++++++++++++++++++++++++++++------
46 arch/xtensa/kernel/vmlinux.lds.S | 4
47 2 files changed, 138 insertions(+), 24 deletions(-)
48
49 --- a/arch/xtensa/kernel/vectors.S
50 +++ b/arch/xtensa/kernel/vectors.S
51 @@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow:
52 beqz a2, 1f # if at start of vector, don't restore
53
54 addi a0, a0, -128
55 - bbsi a0, 8, 1f # don't restore except for overflow 8 and 12
56 - bbsi a0, 7, 2f
57 + bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12
58 +
59 + /*
60 + * This fixup handler is for the extremely unlikely case where the
61 + * overflow handler's reference thru a0 gets a hardware TLB refill
62 + * that bumps out the (distinct, aliasing) TLB entry that mapped its
63 + * prior references thru a9/a13, and where our reference now thru
64 + * a9/a13 gets a 2nd-level miss exception (not hardware TLB refill).
65 + */
66 + movi a2, window_overflow_restore_a0_fixup
67 + s32i a2, a3, EXC_TABLE_FIXUP
68 + l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
69 + xsr a3, excsave1
70 +
71 + bbsi.l a0, 7, 2f
72
73 /*
74 * Restore a0 as saved by _WindowOverflow8().
75 - *
76 - * FIXME: we really need a fixup handler for this L32E,
77 - * for the extremely unlikely case where the overflow handler's
78 - * reference thru a0 gets a hardware TLB refill that bumps out
79 - * the (distinct, aliasing) TLB entry that mapped its prior
80 - * references thru a9, and where our reference now thru a9
81 - * gets a 2nd-level miss exception (not hardware TLB refill).
82 */
83
84 - l32e a2, a9, -16
85 - wsr a2, depc # replace the saved a0
86 - j 1f
87 + l32e a0, a9, -16
88 + wsr a0, depc # replace the saved a0
89 + j 3f
90
91 2:
92 /*
93 * Restore a0 as saved by _WindowOverflow12().
94 - *
95 - * FIXME: we really need a fixup handler for this L32E,
96 - * for the extremely unlikely case where the overflow handler's
97 - * reference thru a0 gets a hardware TLB refill that bumps out
98 - * the (distinct, aliasing) TLB entry that mapped its prior
99 - * references thru a13, and where our reference now thru a13
100 - * gets a 2nd-level miss exception (not hardware TLB refill).
101 */
102
103 - l32e a2, a13, -16
104 - wsr a2, depc # replace the saved a0
105 + l32e a0, a13, -16
106 + wsr a0, depc # replace the saved a0
107 +3:
108 + xsr a3, excsave1
109 + movi a0, 0
110 + s32i a0, a3, EXC_TABLE_FIXUP
111 + s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
112 1:
113 /*
114 * Restore WindowBase while leaving all address registers restored.
115 @@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow:
116
117 s32i a0, a2, PT_DEPC
118
119 +_DoubleExceptionVector_handle_exception:
120 addx4 a0, a0, a3
121 l32i a0, a0, EXC_TABLE_FAST_USER
122 xsr a3, excsave1
123 @@ -464,11 +469,120 @@ _DoubleExceptionVector_WindowOverflow:
124 rotw -3
125 j 1b
126
127 - .end literal_prefix
128
129 ENDPROC(_DoubleExceptionVector)
130
131 /*
132 + * Fixup handler for TLB miss in double exception handler for window owerflow.
133 + * We get here with windowbase set to the window that was being spilled and
134 + * a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12
135 + * (bit set) window.
136 + *
137 + * We do the following here:
138 + * - go to the original window retaining a0 value;
139 + * - set up exception stack to return back to appropriate a0 restore code
140 + * (we'll need to rotate window back and there's no place to save this
141 + * information, use different return address for that);
142 + * - handle the exception;
143 + * - go to the window that was being spilled;
144 + * - set up window_overflow_restore_a0_fixup as a fixup routine;
145 + * - reload a0;
146 + * - restore the original window;
147 + * - reset the default fixup routine;
148 + * - return to user. By the time we get to this fixup handler all information
149 + * about the conditions of the original double exception that happened in
150 + * the window overflow handler is lost, so we just return to userspace to
151 + * retry overflow from start.
152 + *
153 + * a0: value of depc, original value in depc
154 + * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
155 + * a3: exctable, original value in excsave1
156 + */
157 +
158 +ENTRY(window_overflow_restore_a0_fixup)
159 +
160 + rsr a0, ps
161 + extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
162 + rsr a2, windowbase
163 + sub a0, a2, a0
164 + extui a0, a0, 0, 3
165 + l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
166 + xsr a3, excsave1
167 +
168 + _beqi a0, 1, .Lhandle_1
169 + _beqi a0, 3, .Lhandle_3
170 +
171 + .macro overflow_fixup_handle_exception_pane n
172 +
173 + rsr a0, depc
174 + rotw -\n
175 +
176 + xsr a3, excsave1
177 + wsr a2, depc
178 + l32i a2, a3, EXC_TABLE_KSTK
179 + s32i a0, a2, PT_AREG0
180 +
181 + movi a0, .Lrestore_\n
182 + s32i a0, a2, PT_DEPC
183 + rsr a0, exccause
184 + j _DoubleExceptionVector_handle_exception
185 +
186 + .endm
187 +
188 + overflow_fixup_handle_exception_pane 2
189 +.Lhandle_1:
190 + overflow_fixup_handle_exception_pane 1
191 +.Lhandle_3:
192 + overflow_fixup_handle_exception_pane 3
193 +
194 + .macro overflow_fixup_restore_a0_pane n
195 +
196 + rotw \n
197 + /* Need to preserve a0 value here to be able to handle exception
198 + * that may occur on a0 reload from stack. It may occur because
199 + * TLB miss handler may not be atomic and pointer to page table
200 + * may be lost before we get here. There are no free registers,
201 + * so we need to use EXC_TABLE_DOUBLE_SAVE area.
202 + */
203 + xsr a3, excsave1
204 + s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
205 + movi a2, window_overflow_restore_a0_fixup
206 + s32i a2, a3, EXC_TABLE_FIXUP
207 + l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
208 + xsr a3, excsave1
209 + bbsi.l a0, 7, 1f
210 + l32e a0, a9, -16
211 + j 2f
212 +1:
213 + l32e a0, a13, -16
214 +2:
215 + rotw -\n
216 +
217 + .endm
218 +
219 +.Lrestore_2:
220 + overflow_fixup_restore_a0_pane 2
221 +
222 +.Lset_default_fixup:
223 + xsr a3, excsave1
224 + s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
225 + movi a2, 0
226 + s32i a2, a3, EXC_TABLE_FIXUP
227 + l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
228 + xsr a3, excsave1
229 + rfe
230 +
231 +.Lrestore_1:
232 + overflow_fixup_restore_a0_pane 1
233 + j .Lset_default_fixup
234 +.Lrestore_3:
235 + overflow_fixup_restore_a0_pane 3
236 + j .Lset_default_fixup
237 +
238 +ENDPROC(window_overflow_restore_a0_fixup)
239 +
240 + .end literal_prefix
241 +/*
242 * Debug interrupt vector
243 *
244 * There is not much space here, so simply jump to another handler.
245 --- a/arch/xtensa/kernel/vmlinux.lds.S
246 +++ b/arch/xtensa/kernel/vmlinux.lds.S
247 @@ -269,13 +269,13 @@ SECTIONS
248 .UserExceptionVector.literal)
249 SECTION_VECTOR (_DoubleExceptionVector_literal,
250 .DoubleExceptionVector.literal,
251 - DOUBLEEXC_VECTOR_VADDR - 16,
252 + DOUBLEEXC_VECTOR_VADDR - 40,
253 SIZEOF(.UserExceptionVector.text),
254 .UserExceptionVector.text)
255 SECTION_VECTOR (_DoubleExceptionVector_text,
256 .DoubleExceptionVector.text,
257 DOUBLEEXC_VECTOR_VADDR,
258 - 32,
259 + 40,
260 .DoubleExceptionVector.literal)
261
262 . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;