kernel: bump 4.9 to 4.9.109 for 18.06
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.9 / 950-0149-Update-vfpmodule.c.patch
1 From aa00ca3b0296c40a6b5a1ad32258d5b655a28c70 Mon Sep 17 00:00:00 2001
2 From: Claggy3 <stephen.maclagan@hotmail.com>
3 Date: Sat, 11 Feb 2017 14:00:30 +0000
4 Subject: [PATCH] Update vfpmodule.c
5
6 Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m.
7 This patch fixes a problem with VFP state save and restore related
8 to exception handling (panic with message "BUG: unsupported FP
9 instruction in kernel mode") present on VFP11 floating point units
10 (as used with ARM1176JZF-S CPUs, e.g. on first generation Raspberry
11 Pi boards). This patch was developed and discussed on
12
13 https://github.com/raspberrypi/linux/issues/859
14
15 A precondition to see the crashes is that floating point exception
16 traps are enabled. In this case, the VFP11 might determine that a FPU
17 operation needs to trap at a point in time when it is not possible to
18 signal this to the ARM11 core any more. The VFP11 will then set the
19 FPEXC.EX bit and store the trapped opcode in FPINST. (In some cases,
20 a second opcode might have been accepted by the VFP11 before the
21 exception was detected and could be reported to the ARM11 - in this
22 case, the VFP11 also sets FPEXC.FP2V and stores the second opcode in
23 FPINST2.)
24
25 If FPEXC.EX is set, the VFP11 will "bounce" the next FPU opcode issued
26 by the ARM11 CPU, which will be seen by the ARM11 as an undefined opcode
27 trap. The VFP support code examines the FPEXC.EX and FPEXC.FP2V bits
28 to decide what actions to take, i.e., whether to emulate the opcodes
29 found in FPINST and FPINST2, and whether to retry the bounced instruction.
30
31 If a user space application has left the VFP11 in this "pending trap"
32 state, the next FPU opcode issued to the VFP11 might actually be the
33 VSTMIA operation vfp_save_state() uses to store the FPU registers
34 to memory (in our test cases, when building the signal stack frame).
35 In this case, the kernel crashes as described above.
36
37 This patch fixes the problem by making sure that vfp_save_state() is
38 always entered with FPEXC.EX cleared. (The current value of FPEXC has
39 already been saved, so this does not corrupt the context. Clearing
40 FPEXC.EX has no effects on FPINST or FPINST2. Also note that many
41 callers already modify FPEXC by setting FPEXC.EN before invoking
42 vfp_save_state().)
43
44 This patch also addresses a second problem related to FPEXC.EX: After
45 returning from signal handling, the kernel reloads the VFP context
46 from the user mode stack. However, the current code explicitly clears
47 both FPEXC.EX and FPEXC.FP2V during reload. As VFP11 requires these
48 bits to be preserved, this patch disables clearing them for VFP
49 implementations belonging to architecture 1. There should be no
50 negative side effects: the user can set both bits by executing FPU
51 opcodes anyway, and while user code may now place arbitrary values
52 into FPINST and FPINST2 (e.g., non-VFP ARM opcodes) the VFP support
53 code knows which instructions can be emulated, and rejects other
54 opcodes with "unhandled bounce" messages, so there should be no
55 security impact from allowing reloading FPEXC.EX and FPEXC.FP2V.
56
57 Signed-off-by: Christopher Alexander Tobias Schulze <cat.schulze@alice-dsl.net>
58 ---
59 arch/arm/vfp/vfpmodule.c | 25 +++++++++++++++++++------
60 1 file changed, 19 insertions(+), 6 deletions(-)
61
62 --- a/arch/arm/vfp/vfpmodule.c
63 +++ b/arch/arm/vfp/vfpmodule.c
64 @@ -179,8 +179,11 @@ static int vfp_notifier(struct notifier_
65 * case the thread migrates to a different CPU. The
66 * restoring is done lazily.
67 */
68 - if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
69 + if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) {
70 + /* vfp_save_state oopses on VFP11 if EX bit set */
71 + fmxr(FPEXC, fpexc & ~FPEXC_EX);
72 vfp_save_state(vfp_current_hw_state[cpu], fpexc);
73 + }
74 #endif
75
76 /*
77 @@ -463,13 +466,16 @@ static int vfp_pm_suspend(void)
78 /* if vfp is on, then save state for resumption */
79 if (fpexc & FPEXC_EN) {
80 pr_debug("%s: saving vfp state\n", __func__);
81 + /* vfp_save_state oopses on VFP11 if EX bit set */
82 + fmxr(FPEXC, fpexc & ~FPEXC_EX);
83 vfp_save_state(&ti->vfpstate, fpexc);
84
85 /* disable, just in case */
86 fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
87 } else if (vfp_current_hw_state[ti->cpu]) {
88 #ifndef CONFIG_SMP
89 - fmxr(FPEXC, fpexc | FPEXC_EN);
90 + /* vfp_save_state oopses on VFP11 if EX bit set */
91 + fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
92 vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
93 fmxr(FPEXC, fpexc);
94 #endif
95 @@ -532,7 +538,8 @@ void vfp_sync_hwstate(struct thread_info
96 /*
97 * Save the last VFP state on this CPU.
98 */
99 - fmxr(FPEXC, fpexc | FPEXC_EN);
100 + /* vfp_save_state oopses on VFP11 if EX bit set */
101 + fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
102 vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
103 fmxr(FPEXC, fpexc);
104 }
105 @@ -604,6 +611,7 @@ int vfp_restore_user_hwstate(struct user
106 struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
107 unsigned long fpexc;
108 int err = 0;
109 + u32 fpsid = fmrx(FPSID);
110
111 /* Disable VFP to avoid corrupting the new thread state. */
112 vfp_flush_hwstate(thread);
113 @@ -627,8 +635,12 @@ int vfp_restore_user_hwstate(struct user
114 /* Ensure the VFP is enabled. */
115 fpexc |= FPEXC_EN;
116
117 - /* Ensure FPINST2 is invalid and the exception flag is cleared. */
118 - fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
119 + /* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */
120 + if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) {
121 + /* Ensure FPINST2 is invalid and the exception flag is cleared. */
122 + fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
123 + }
124 +
125 hwstate->fpexc = fpexc;
126
127 __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
128 @@ -698,7 +710,8 @@ void kernel_neon_begin(void)
129 cpu = get_cpu();
130
131 fpexc = fmrx(FPEXC) | FPEXC_EN;
132 - fmxr(FPEXC, fpexc);
133 + /* vfp_save_state oopses on VFP11 if EX bit set */
134 + fmxr(FPEXC, fpexc & ~FPEXC_EX);
135
136 /*
137 * Save the userland NEON/VFP state. Under UP,