mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-10-31 18:09:19 +00:00
bbd24eba8a
The Undef abort handler in the kernel reads the undefined instruction from user space. If the page table was modified from another CPU, the user access could fail and do_page_fault() will be executed with interrupts disabled. This can potentially deadlock on ARM11MPCore or on Cortex-A15 with erratum 798181 workaround enabled (both implying IPI for TLB maintenance with page table lock held). This patch enables the IRQs in __und_usr before attempting to read the instruction from user space. CRs-Fixed: 685372 Change-Id: Id6dc049b923b577373d38bb66a8404711c1a60f5 Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Tested-by: Arun KS <getarunks@gmail.com> Cc: Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ryan Mallon <rmallon@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Git-commit: 1417a6b8dc4db73055be9a3aa288b050e9dc06ab Git-repo: git://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git Signed-off-by: Kishan Kumar <kishank@codeaurora.org>
70 lines
1.7 KiB
ArmAsm
70 lines
1.7 KiB
ArmAsm
/*
|
|
* linux/arch/arm/vfp/entry.S
|
|
*
|
|
* Copyright (C) 2004 ARM Limited.
|
|
* Written by Deep Blue Solutions Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <asm/thread_info.h>
|
|
#include <asm/vfpmacros.h>
|
|
#include "../kernel/entry-header.S"
|
|
|
|
@ VFP entry point.
|
|
@
|
|
@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb)
|
|
@ r2 = PC value to resume execution after successful emulation
|
|
@ r9 = normal "successful" return address
|
|
@ r10 = this threads thread_info structure
|
|
@ lr = unrecognised instruction return address
|
|
@ IRQs enabled.
|
|
@
|
|
ENTRY(do_vfp)
|
|
#ifdef CONFIG_PREEMPT_COUNT
|
|
ldr r4, [r10, #TI_PREEMPT] @ get preempt count
|
|
add r11, r4, #1 @ increment it
|
|
str r11, [r10, #TI_PREEMPT]
|
|
#endif
|
|
ldr r4, .LCvfp
|
|
ldr r11, [r10, #TI_CPU] @ CPU number
|
|
add r10, r10, #TI_VFPSTATE @ r10 = workspace
|
|
ldr pc, [r4] @ call VFP entry point
|
|
ENDPROC(do_vfp)
|
|
|
|
ENTRY(vfp_null_entry)
|
|
#ifdef CONFIG_PREEMPT_COUNT
|
|
get_thread_info r10
|
|
ldr r4, [r10, #TI_PREEMPT] @ get preempt count
|
|
sub r11, r4, #1 @ decrement it
|
|
str r11, [r10, #TI_PREEMPT]
|
|
#endif
|
|
mov pc, lr
|
|
ENDPROC(vfp_null_entry)
|
|
|
|
.align 2
|
|
.LCvfp:
|
|
.word vfp_vector
|
|
|
|
@ This code is called if the VFP does not exist. It needs to flag the
|
|
@ failure to the VFP initialisation code.
|
|
|
|
__INIT
|
|
ENTRY(vfp_testing_entry)
|
|
#ifdef CONFIG_PREEMPT_COUNT
|
|
get_thread_info r10
|
|
ldr r4, [r10, #TI_PREEMPT] @ get preempt count
|
|
sub r11, r4, #1 @ decrement it
|
|
str r11, [r10, #TI_PREEMPT]
|
|
#endif
|
|
ldr r0, VFP_arch_address
|
|
str r0, [r0] @ set to non-zero value
|
|
mov pc, r9 @ we have handled the fault
|
|
ENDPROC(vfp_testing_entry)
|
|
|
|
.align 2
|
|
VFP_arch_address:
|
|
.word VFP_arch
|
|
|
|
__FINIT
|