summaryrefslogtreecommitdiff
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2018-06-21 15:37:37 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2018-06-21 15:37:37 +0200
commite86ab6530fd4e461ae622b6c1ff72359952a7189 (patch)
treefb387e644216e47c13da26c5dbecab6822714393 /arch/arm/mm
parente81dd8a3500fea94ce8786554cbc29bc6b2a9207 (diff)
parente78bb38b883c42edf81766a1d557aed74458e08f (diff)
Merge tag 'tegra-l4t-r21.7' into toradex_tk1_l4t_r21.7-next
Merge NVIDIA's latest Linux for Tegra aka L4T R21.7 Linux kernel changes from git://nv-tegra.nvidia.com/linux-3.10.git commit: e78bb38b883c42edf81766a1d557aed74458e08f Conflicts involved missing 24-bit LVDS support and a single whitespace aka tab difference in drivers/video/tegra/dc/sor.c. Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/Kconfig17
-rw-r--r--arch/arm/mm/fault.c23
-rw-r--r--arch/arm/mm/fsr-2level.c4
-rw-r--r--arch/arm/mm/fsr-3level.c69
-rw-r--r--arch/arm/mm/mmap.c4
-rw-r--r--arch/arm/mm/proc-v7-2level.S12
-rw-r--r--arch/arm/mm/proc-v7-3level.S15
-rw-r--r--arch/arm/mm/proc-v7.S43
8 files changed, 181 insertions, 6 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 2c7e308f8cab..07c3309b6288 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -947,3 +947,20 @@ config ARM_SAVE_DEBUG_CONTEXT_NO_LOCK
the ARM debug registers across CPU powerdown. This option
should not be selected unless you are actively debugging
the context save/restore code. If unsure, say N.
+
+config HARDEN_BRANCH_PREDICTOR
+ bool "Harden the branch predictor against aliasing attacks" if EXPERT
+ default y
+ help
+ Speculation attacks against some high-performance processors rely on
+ being able to manipulate the branch predictor for a victim context by
+ executing aliasing branches in the attacker context. Such attacks
+ can be partially mitigated against by clearing internal branch
+ predictor state and limiting the prediction logic in some situations.
+
+ This config option will take CPU-specific actions to harden the
+ branch predictor against aliasing attacks and may rely on specific
+ instruction sequences or control bits being set by the system
+ firmware.
+
+ If unsure, say Y.
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 9820ad4b80c0..e8f42821a206 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -20,11 +20,13 @@
#include <linux/highmem.h>
#include <linux/perf_event.h>
+#include <asm/cp15.h>
#include <asm/exception.h>
#include <asm/pgtable.h>
#include <asm/system_misc.h>
#include <asm/system_info.h>
#include <asm/tlbflush.h>
+#include <asm/cputype.h>
#include "fault.h"
@@ -393,12 +395,33 @@ no_context:
__do_kernel_fault(mm, addr, fsr, regs);
return 0;
}
+
+static int __maybe_unused
+do_pabt_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+ if (addr > TASK_SIZE) {
+ switch (read_cpuid_part_number()) {
+ case ARM_CPU_PART_CORTEX_A15:
+ write_sysreg(0, ICIALLU);
+ break;
+ }
+ }
+#endif
+ return do_page_fault(addr, fsr, regs);
+}
#else /* CONFIG_MMU */
static int
do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
return 0;
}
+
+static int
+do_pabt_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+ return 0;
+}
#endif /* CONFIG_MMU */
/*
diff --git a/arch/arm/mm/fsr-2level.c b/arch/arm/mm/fsr-2level.c
index 18ca74c0f341..4cede9bc7722 100644
--- a/arch/arm/mm/fsr-2level.c
+++ b/arch/arm/mm/fsr-2level.c
@@ -50,7 +50,7 @@ static struct fsr_info ifsr_info[] = {
{ do_bad, SIGBUS, 0, "unknown 4" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" },
- { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
{ do_bad, SIGBUS, 0, "unknown 10" },
@@ -58,7 +58,7 @@ static struct fsr_info ifsr_info[] = {
{ do_bad, SIGBUS, 0, "external abort on translation" },
{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
- { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
{ do_bad, SIGBUS, 0, "unknown 16" },
{ do_bad, SIGBUS, 0, "unknown 17" },
{ do_bad, SIGBUS, 0, "unknown 18" },
diff --git a/arch/arm/mm/fsr-3level.c b/arch/arm/mm/fsr-3level.c
index 47f4c6fb25ba..791ef0c66741 100644
--- a/arch/arm/mm/fsr-3level.c
+++ b/arch/arm/mm/fsr-3level.c
@@ -65,4 +65,73 @@ static struct fsr_info fsr_info[] = {
{ do_bad, SIGBUS, 0, "unknown 63" },
};
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+static struct fsr_info ifsr_info[] = {
+ { do_bad, SIGBUS, 0, "unknown 0" },
+ { do_bad, SIGBUS, 0, "unknown 1" },
+ { do_bad, SIGBUS, 0, "unknown 2" },
+ { do_bad, SIGBUS, 0, "unknown 3" },
+ { do_bad, SIGBUS, 0, "reserved translation fault" },
+ { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" },
+ { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
+ { do_bad, SIGBUS, 0, "reserved access flag fault" },
+ { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
+ { do_bad, SIGBUS, 0, "reserved permission fault" },
+ { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
+ { do_pabt_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
+ { do_bad, SIGBUS, 0, "synchronous external abort" },
+ { do_bad, SIGBUS, 0, "asynchronous external abort" },
+ { do_bad, SIGBUS, 0, "unknown 18" },
+ { do_bad, SIGBUS, 0, "unknown 19" },
+ { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
+ { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
+ { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
+ { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
+ { do_bad, SIGBUS, 0, "synchronous parity error" },
+ { do_bad, SIGBUS, 0, "asynchronous parity error" },
+ { do_bad, SIGBUS, 0, "unknown 26" },
+ { do_bad, SIGBUS, 0, "unknown 27" },
+ { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
+ { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
+ { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
+ { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
+ { do_bad, SIGBUS, 0, "unknown 32" },
+ { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" },
+ { do_bad, SIGBUS, 0, "debug event" },
+ { do_bad, SIGBUS, 0, "unknown 35" },
+ { do_bad, SIGBUS, 0, "unknown 36" },
+ { do_bad, SIGBUS, 0, "unknown 37" },
+ { do_bad, SIGBUS, 0, "unknown 38" },
+ { do_bad, SIGBUS, 0, "unknown 39" },
+ { do_bad, SIGBUS, 0, "unknown 40" },
+ { do_bad, SIGBUS, 0, "unknown 41" },
+ { do_bad, SIGBUS, 0, "unknown 42" },
+ { do_bad, SIGBUS, 0, "unknown 43" },
+ { do_bad, SIGBUS, 0, "unknown 44" },
+ { do_bad, SIGBUS, 0, "unknown 45" },
+ { do_bad, SIGBUS, 0, "unknown 46" },
+ { do_bad, SIGBUS, 0, "unknown 47" },
+ { do_bad, SIGBUS, 0, "unknown 48" },
+ { do_bad, SIGBUS, 0, "unknown 49" },
+ { do_bad, SIGBUS, 0, "unknown 50" },
+ { do_bad, SIGBUS, 0, "unknown 51" },
+ { do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" },
+ { do_bad, SIGBUS, 0, "unknown 53" },
+ { do_bad, SIGBUS, 0, "unknown 54" },
+ { do_bad, SIGBUS, 0, "unknown 55" },
+ { do_bad, SIGBUS, 0, "unknown 56" },
+ { do_bad, SIGBUS, 0, "unknown 57" },
+ { do_bad, SIGBUS, 0, "implementation fault (coprocessor abort)" },
+ { do_bad, SIGBUS, 0, "unknown 59" },
+ { do_bad, SIGBUS, 0, "unknown 60" },
+ { do_bad, SIGBUS, 0, "unknown 61" },
+ { do_bad, SIGBUS, 0, "unknown 62" },
+ { do_bad, SIGBUS, 0, "unknown 63" },
+};
+#else
#define ifsr_info fsr_info
++#endif
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index a5b1934e711b..86cda2e8ec19 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -90,7 +90,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
- (!vma || addr + len <= vma->vm_start))
+ (!vma || addr + len <= vm_start_gap(vma)))
return addr;
}
@@ -155,7 +155,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
addr = PAGE_ALIGN(addr);
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
- (!vma || addr + len <= vma->vm_start))
+ (!vma || addr + len <= vm_start_gap(vma)))
return addr;
}
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index a0cf0dc9f0d7..48db62324291 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -36,7 +36,16 @@
*
* It is assumed that:
* - we are not using split page tables
- */
+ *
+ * Cortex-A15 requires ACTLR[0] to be set from secure in order
+ * for the icache invalidation to also invalidate the BTB.
+ */
+ENTRY(cpu_v7_icinv_switch_mm)
+#ifdef CONFIG_MMU
+ mcr p15, 0, r0, c7, c5, 0 @ ICIALLU
+ /* Fall through to switch_mm... */
+#endif
+
ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
mov r2, #0
@@ -61,6 +70,7 @@ ENTRY(cpu_v7_switch_mm)
#endif
mov pc, lr
ENDPROC(cpu_v7_switch_mm)
+ENDPROC(cpu_v7_icinv_switch_mm)
/*
* cpu_v7_set_pte_ext(ptep, pte)
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index e377cc4031b0..e2bb1ae55047 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -53,6 +53,19 @@
* Set the translation table base pointer to be pgd_phys (physical address of
* the new TTB).
*/
+ENTRY(cpu_v7_icinv_switch_mm)
+#ifdef CONFIG_MMU
+ /*
+ * Cortex-A15 requires ACTLR[0] to be set from secure in order
+ * for the icache invalidation to also invalidate the BTB.
+ */
+ mcr p15, 0, r0, c7, c5, 0 @ ICIALLU
+ /* Fall through to switch_mm... */
+#endif
+ENTRY(cpu_v7_btbinv_switch_mm)
+#ifdef CONFIG_MMU
+ mcr p15, 0, r0, c7, c5, 6 @ flush BTAC/BTB
+#endif
ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
mmid r2, r2 @ get mm->context.id
@@ -64,6 +77,8 @@ ENTRY(cpu_v7_switch_mm)
#endif
mov pc, lr
ENDPROC(cpu_v7_switch_mm)
+ENDPROC(cpu_v7_btbinv_switch_mm)
+ENDPROC(cpu_v7_icinv_switch_mm)
/*
* cpu_v7_set_pte_ext(ptep, pte)
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index d1dea91517e0..322ecf52c2a7 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -415,6 +415,46 @@ start_restore_wpt:
ENDPROC(cpu_v7_do_resume)
#endif
+/*
+ * Cortex-A15
+ */
+ globl_equ cpu_ca15_proc_init, cpu_v7_proc_init
+ globl_equ cpu_ca15_proc_fin, cpu_v7_proc_fin
+ globl_equ cpu_ca15_reset, cpu_v7_reset
+ globl_equ cpu_ca15_do_idle, cpu_v7_do_idle
+ globl_equ cpu_ca15_dcache_clean_area, cpu_v7_dcache_clean_area
+ globl_equ cpu_ca15_set_pte_ext, cpu_v7_set_pte_ext
+ globl_equ cpu_ca15_suspend_size, cpu_v7_suspend_size
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+ globl_equ cpu_ca15_switch_mm, cpu_v7_icinv_switch_mm
+#else
+ globl_equ cpu_ca15_switch_mm, cpu_v7_switch_mm
+#endif
+#ifdef CONFIG_ARM_CPU_SUSPEND
+ globl_equ cpu_ca15_do_suspend, cpu_v7_do_suspend
+ globl_equ cpu_ca15_do_resume, cpu_v7_do_resume
+#endif
+
+/*
+ * Cortex-A12/A17
+ */
+ globl_equ cpu_ca17_proc_init, cpu_v7_proc_init
+ globl_equ cpu_ca17_proc_fin, cpu_v7_proc_fin
+ globl_equ cpu_ca17_reset, cpu_v7_reset
+ globl_equ cpu_ca17_do_idle, cpu_v7_do_idle
+ globl_equ cpu_ca17_dcache_clean_area, cpu_v7_dcache_clean_area
+ globl_equ cpu_ca17_set_pte_ext, cpu_v7_set_pte_ext
+ globl_equ cpu_ca17_suspend_size, cpu_v7_suspend_size
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+ globl_equ cpu_ca17_switch_mm, cpu_v7_btbinv_switch_mm
+#else
+ globl_equ cpu_ca17_switch_mm, cpu_v7_switch_mm
+#endif
+#ifdef CONFIG_ARM_CPU_SUSPEND
+ globl_equ cpu_ca17_do_suspend, cpu_v7_do_suspend
+ globl_equ cpu_ca17_do_resume, cpu_v7_do_resume
+#endif
+
#ifdef CONFIG_CPU_PJ4B
globl_equ cpu_pj4b_switch_mm, cpu_v7_switch_mm
globl_equ cpu_pj4b_set_pte_ext, cpu_v7_set_pte_ext
@@ -722,6 +762,7 @@ __v7_setup_stack:
@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+ define_processor_functions ca15, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
#ifdef CONFIG_CPU_PJ4B
define_processor_functions pj4b, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
#endif
@@ -818,7 +859,7 @@ __v7_ca15mp_r3_proc_info:
__v7_ca15mp_proc_info:
.long 0x410fc0f0
.long 0xff0ffff0
- __v7_proc __v7_ca15mp_setup
+ __v7_proc __v7_ca15mp_setup, proc_fns = ca15_processor_functions
.size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
/*