]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - 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
CommitLineData
da1ce37e
GKH
1From 17290231df16eeee5dfc198dbf5ee4b419996dcd Mon Sep 17 00:00:00 2001
2From: Max Filippov <jcmvbkbc@gmail.com>
3Date: Sat, 24 May 2014 21:48:28 +0400
4Subject: xtensa: add fixup for double exception raised in window overflow
5
6From: Max Filippov <jcmvbkbc@gmail.com>
7
8commit 17290231df16eeee5dfc198dbf5ee4b419996dcd upstream.
9
10There are two FIXMEs in the double exception handler 'for the extremely
11unlikely case'. This case gets hit by gcc during kernel build once in
12a few hours, resulting in an unrecoverable exception condition.
13
14Provide missing fixup routine to handle this case. Double exception
15literals now need 8 more bytes, add them to the linker script.
16
17Also replace bbsi instructions with bbsi.l as we're branching depending
18on 8th and 7th LSB-based bits of exception address.
19
20This may be tested by adding the explicit DTLB invalidation to window
21overflow 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
41Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
42Signed-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;