mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-28 09:39:00 +00:00
f5919b65d4
Patch generation process: - rebase rpi/rpi-4.14.y on v4.14.89 from linux-stable - git format-patch v4.14.89 Patches skipped during rebase: - lan78xx: Read MAC address from DT if present - lan78xx: Enable LEDs and auto-negotiation - Revert "softirq: Let ksoftirqd do its job" - sc16is7xx: Fix for multi-channel stall - lan78xx: Ignore DT MAC address if already valid - lan78xx: Simple patch to prevent some crashes - tcp_write_queue_purge clears all the SKBs in the write queue - Revert "lan78xx: Simple patch to prevent some crashes" - lan78xx: Connect phy early - Arm: mm: ftrace: Only set text back to ro after kernel has been marked ro - Revert "Revert "softirq: Let ksoftirqd do its job"" - ASoC: cs4265: SOC_SINGLE register value error fix - Revert "ASoC: cs4265: SOC_SINGLE register value error fix" - Revert "net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends" - Revert "Revert "net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends"" Patches dropped after rebase: - net: Add non-mainline source for rtl8192cu wlan - net: Fix rtl8192cu build errors on other platforms - brcm: adds support for BCM43341 wifi - brcmfmac: Mute expected startup 'errors' - ARM64: Fix build break for RTL8187/RTL8192CU wifi - ARM64: Enable RTL8187/RTL8192CU wifi in build config - This is the driver for Sony CXD2880 DVB-T2/T tuner + demodulator - brcmfmac: add CLM download support - brcmfmac: request_firmware_direct is quieter - Sets the BCDC priority to constant 0 - brcmfmac: Disable ARP offloading when promiscuous - brcmfmac: Avoid possible out-of-bounds read - brcmfmac: Delete redundant length check - net: rtl8192cu: Normalize indentation - net: rtl8192cu: Fix implicit fallthrough warnings - Revert "Sets the BCDC priority to constant 0" - media: cxd2880: Bump to match 4.18.y version - media: cxd2880-spi: Bump to match 4.18.y version - Revert "mm: alloc_contig: re-allow CMA to compact FS pages" - Revert "Revert "mm: alloc_contig: re-allow CMA to compact FS pages"" - cxd2880: CXD2880_SPI_DRV should select DVB_CXD2880 with MEDIA_SUBDRV_AUTOSELECT - 950-0421-HID-hid-bigbenff-driver-for-BigBen-Interactive-PS3OF.patch - 950-0453-Add-hid-bigbenff-to-list-of-have_special_driver-for-.patch Make I2C built-in instead of modular as in upstream defconfig; also the easiest way to get MFD_ARIZONA enabled, which is required by kmod-sound-soc-rpi-cirrus. Add missing compatible strings from 4.9/960-add-rasbperrypi-compatible.patch, using upstream names for compute modules. Add extra patch to enable the LEDs on lan78xx. Compile-tested: bcm2708, bcm2709, bcm2710 (with CONFIG_ALL_KMODS=y) Runtime-tested: bcm2708, bcm2710 Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
139 lines
5.7 KiB
Diff
139 lines
5.7 KiB
Diff
From 5abe6a0ebe150f320a4ca0ed73b2e15fca1b16fd Mon Sep 17 00:00:00 2001
|
|
From: Claggy3 <stephen.maclagan@hotmail.com>
|
|
Date: Sat, 11 Feb 2017 14:00:30 +0000
|
|
Subject: [PATCH 031/454] Update vfpmodule.c
|
|
|
|
Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m.
|
|
This patch fixes a problem with VFP state save and restore related
|
|
to exception handling (panic with message "BUG: unsupported FP
|
|
instruction in kernel mode") present on VFP11 floating point units
|
|
(as used with ARM1176JZF-S CPUs, e.g. on first generation Raspberry
|
|
Pi boards). This patch was developed and discussed on
|
|
|
|
https://github.com/raspberrypi/linux/issues/859
|
|
|
|
A precondition to see the crashes is that floating point exception
|
|
traps are enabled. In this case, the VFP11 might determine that a FPU
|
|
operation needs to trap at a point in time when it is not possible to
|
|
signal this to the ARM11 core any more. The VFP11 will then set the
|
|
FPEXC.EX bit and store the trapped opcode in FPINST. (In some cases,
|
|
a second opcode might have been accepted by the VFP11 before the
|
|
exception was detected and could be reported to the ARM11 - in this
|
|
case, the VFP11 also sets FPEXC.FP2V and stores the second opcode in
|
|
FPINST2.)
|
|
|
|
If FPEXC.EX is set, the VFP11 will "bounce" the next FPU opcode issued
|
|
by the ARM11 CPU, which will be seen by the ARM11 as an undefined opcode
|
|
trap. The VFP support code examines the FPEXC.EX and FPEXC.FP2V bits
|
|
to decide what actions to take, i.e., whether to emulate the opcodes
|
|
found in FPINST and FPINST2, and whether to retry the bounced instruction.
|
|
|
|
If a user space application has left the VFP11 in this "pending trap"
|
|
state, the next FPU opcode issued to the VFP11 might actually be the
|
|
VSTMIA operation vfp_save_state() uses to store the FPU registers
|
|
to memory (in our test cases, when building the signal stack frame).
|
|
In this case, the kernel crashes as described above.
|
|
|
|
This patch fixes the problem by making sure that vfp_save_state() is
|
|
always entered with FPEXC.EX cleared. (The current value of FPEXC has
|
|
already been saved, so this does not corrupt the context. Clearing
|
|
FPEXC.EX has no effects on FPINST or FPINST2. Also note that many
|
|
callers already modify FPEXC by setting FPEXC.EN before invoking
|
|
vfp_save_state().)
|
|
|
|
This patch also addresses a second problem related to FPEXC.EX: After
|
|
returning from signal handling, the kernel reloads the VFP context
|
|
from the user mode stack. However, the current code explicitly clears
|
|
both FPEXC.EX and FPEXC.FP2V during reload. As VFP11 requires these
|
|
bits to be preserved, this patch disables clearing them for VFP
|
|
implementations belonging to architecture 1. There should be no
|
|
negative side effects: the user can set both bits by executing FPU
|
|
opcodes anyway, and while user code may now place arbitrary values
|
|
into FPINST and FPINST2 (e.g., non-VFP ARM opcodes) the VFP support
|
|
code knows which instructions can be emulated, and rejects other
|
|
opcodes with "unhandled bounce" messages, so there should be no
|
|
security impact from allowing reloading FPEXC.EX and FPEXC.FP2V.
|
|
|
|
Signed-off-by: Christopher Alexander Tobias Schulze <cat.schulze@alice-dsl.net>
|
|
---
|
|
arch/arm/vfp/vfpmodule.c | 26 ++++++++++++++++++++------
|
|
1 file changed, 20 insertions(+), 6 deletions(-)
|
|
|
|
--- a/arch/arm/vfp/vfpmodule.c
|
|
+++ b/arch/arm/vfp/vfpmodule.c
|
|
@@ -179,8 +179,11 @@ static int vfp_notifier(struct notifier_
|
|
* case the thread migrates to a different CPU. The
|
|
* restoring is done lazily.
|
|
*/
|
|
- if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
|
|
+ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) {
|
|
+ /* vfp_save_state oopses on VFP11 if EX bit set */
|
|
+ fmxr(FPEXC, fpexc & ~FPEXC_EX);
|
|
vfp_save_state(vfp_current_hw_state[cpu], fpexc);
|
|
+ }
|
|
#endif
|
|
|
|
/*
|
|
@@ -463,13 +466,16 @@ static int vfp_pm_suspend(void)
|
|
/* if vfp is on, then save state for resumption */
|
|
if (fpexc & FPEXC_EN) {
|
|
pr_debug("%s: saving vfp state\n", __func__);
|
|
+ /* vfp_save_state oopses on VFP11 if EX bit set */
|
|
+ fmxr(FPEXC, fpexc & ~FPEXC_EX);
|
|
vfp_save_state(&ti->vfpstate, fpexc);
|
|
|
|
/* disable, just in case */
|
|
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
|
} else if (vfp_current_hw_state[ti->cpu]) {
|
|
#ifndef CONFIG_SMP
|
|
- fmxr(FPEXC, fpexc | FPEXC_EN);
|
|
+ /* vfp_save_state oopses on VFP11 if EX bit set */
|
|
+ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
|
|
vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
|
|
fmxr(FPEXC, fpexc);
|
|
#endif
|
|
@@ -532,7 +538,8 @@ void vfp_sync_hwstate(struct thread_info
|
|
/*
|
|
* Save the last VFP state on this CPU.
|
|
*/
|
|
- fmxr(FPEXC, fpexc | FPEXC_EN);
|
|
+ /* vfp_save_state oopses on VFP11 if EX bit set */
|
|
+ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
|
|
vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
|
|
fmxr(FPEXC, fpexc);
|
|
}
|
|
@@ -602,6 +609,8 @@ int vfp_restore_user_hwstate(struct user
|
|
struct thread_info *thread = current_thread_info();
|
|
struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
|
|
unsigned long fpexc;
|
|
+ int err = 0;
|
|
+ u32 fpsid = fmrx(FPSID);
|
|
|
|
/* Disable VFP to avoid corrupting the new thread state. */
|
|
vfp_flush_hwstate(thread);
|
|
@@ -624,8 +633,12 @@ int vfp_restore_user_hwstate(struct user
|
|
/* Ensure the VFP is enabled. */
|
|
fpexc |= FPEXC_EN;
|
|
|
|
- /* Ensure FPINST2 is invalid and the exception flag is cleared. */
|
|
- fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
|
|
+ /* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */
|
|
+ if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) {
|
|
+ /* Ensure FPINST2 is invalid and the exception flag is cleared. */
|
|
+ fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
|
|
+ }
|
|
+
|
|
hwstate->fpexc = fpexc;
|
|
|
|
hwstate->fpinst = ufp_exc->fpinst;
|
|
@@ -695,7 +708,8 @@ void kernel_neon_begin(void)
|
|
cpu = get_cpu();
|
|
|
|
fpexc = fmrx(FPEXC) | FPEXC_EN;
|
|
- fmxr(FPEXC, fpexc);
|
|
+ /* vfp_save_state oopses on VFP11 if EX bit set */
|
|
+ fmxr(FPEXC, fpexc & ~FPEXC_EX);
|
|
|
|
/*
|
|
* Save the userland NEON/VFP state. Under UP,
|