diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-26 18:03:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-26 18:03:49 -0500 |
commit | bbecb1cfcca55f98cfcb62fa36a32d79975d8816 (patch) | |
tree | ac86a653ea2c9e3c0352b7975026fde14dd3dec1 | |
parent | dec0029a59779d8279dde663ef8abe9824ee5773 (diff) | |
parent | 8bafae202c82dc257f649ea3c275a0f35ee15113 (diff) |
Merge branch 'fixes' of git://git.armlinux.org.uk/~rmk/linux-arm
Pull ARM fixes from Russell King:
- LPAE fixes for kernel-readonly regions
- Fix for get_user_pages_fast on LPAE systems
- avoid tying decompressor to a particular platform if DEBUG_LL is
enabled
- BUG if we attempt to return to userspace but the to-be-restored PSR
value keeps us in privileged mode (defeating an issue that ftracetest
found)
* 'fixes' of git://git.armlinux.org.uk/~rmk/linux-arm:
ARM: BUG if jumping to usermode address in kernel mode
ARM: 8722/1: mm: make STRICT_KERNEL_RWX effective for LPAE
ARM: 8721/1: mm: dump: check hardware RO bit for LPAE
ARM: make decompressor debug output user selectable
ARM: fix get_user_pages_fast
-rw-r--r-- | arch/arm/Kconfig.debug | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/assembler.h | 18 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 12 | ||||
-rw-r--r-- | arch/arm/kernel/entry-header.S | 6 | ||||
-rw-r--r-- | arch/arm/mm/dump.c | 4 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 4 |
6 files changed, 42 insertions, 6 deletions
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 12b8c8f8ec07..17685e19aed8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -1776,9 +1776,9 @@ config DEBUG_UART_8250_FLOW_CONTROL | |||
1776 | default y if ARCH_EBSA110 || DEBUG_FOOTBRIDGE_COM1 || DEBUG_GEMINI || ARCH_RPC | 1776 | default y if ARCH_EBSA110 || DEBUG_FOOTBRIDGE_COM1 || DEBUG_GEMINI || ARCH_RPC |
1777 | 1777 | ||
1778 | config DEBUG_UNCOMPRESS | 1778 | config DEBUG_UNCOMPRESS |
1779 | bool | 1779 | bool "Enable decompressor debugging via DEBUG_LL output" |
1780 | depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M | 1780 | depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M |
1781 | default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ | 1781 | depends on DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ |
1782 | (!DEBUG_TEGRA_UART || !ZBOOT_ROM) && \ | 1782 | (!DEBUG_TEGRA_UART || !ZBOOT_ROM) && \ |
1783 | !DEBUG_BRCMSTB_UART | 1783 | !DEBUG_BRCMSTB_UART |
1784 | help | 1784 | help |
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index ad301f107dd2..bc8d4bbd82e2 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
@@ -518,4 +518,22 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) | |||
518 | #endif | 518 | #endif |
519 | .endm | 519 | .endm |
520 | 520 | ||
521 | .macro bug, msg, line | ||
522 | #ifdef CONFIG_THUMB2_KERNEL | ||
523 | 1: .inst 0xde02 | ||
524 | #else | ||
525 | 1: .inst 0xe7f001f2 | ||
526 | #endif | ||
527 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
528 | .pushsection .rodata.str, "aMS", %progbits, 1 | ||
529 | 2: .asciz "\msg" | ||
530 | .popsection | ||
531 | .pushsection __bug_table, "aw" | ||
532 | .align 2 | ||
533 | .word 1b, 2b | ||
534 | .hword \line | ||
535 | .popsection | ||
536 | #endif | ||
537 | .endm | ||
538 | |||
521 | #endif /* __ASM_ASSEMBLER_H__ */ | 539 | #endif /* __ASM_ASSEMBLER_H__ */ |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 1c462381c225..150ece66ddf3 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -232,6 +232,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
232 | #define pte_valid_user(pte) \ | 232 | #define pte_valid_user(pte) \ |
233 | (pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte)) | 233 | (pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte)) |
234 | 234 | ||
235 | static inline bool pte_access_permitted(pte_t pte, bool write) | ||
236 | { | ||
237 | pteval_t mask = L_PTE_PRESENT | L_PTE_USER; | ||
238 | pteval_t needed = mask; | ||
239 | |||
240 | if (write) | ||
241 | mask |= L_PTE_RDONLY; | ||
242 | |||
243 | return (pte_val(pte) & mask) == needed; | ||
244 | } | ||
245 | #define pte_access_permitted pte_access_permitted | ||
246 | |||
235 | #if __LINUX_ARM_ARCH__ < 6 | 247 | #if __LINUX_ARM_ARCH__ < 6 |
236 | static inline void __sync_icache_dcache(pte_t pteval) | 248 | static inline void __sync_icache_dcache(pte_t pteval) |
237 | { | 249 | { |
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index d523cd8439a3..7f4d80c2db6b 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S | |||
@@ -300,6 +300,8 @@ | |||
300 | mov r2, sp | 300 | mov r2, sp |
301 | ldr r1, [r2, #\offset + S_PSR] @ get calling cpsr | 301 | ldr r1, [r2, #\offset + S_PSR] @ get calling cpsr |
302 | ldr lr, [r2, #\offset + S_PC]! @ get pc | 302 | ldr lr, [r2, #\offset + S_PC]! @ get pc |
303 | tst r1, #0xcf | ||
304 | bne 1f | ||
303 | msr spsr_cxsf, r1 @ save in spsr_svc | 305 | msr spsr_cxsf, r1 @ save in spsr_svc |
304 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) | 306 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) |
305 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | 307 | @ We must avoid clrex due to Cortex-A15 erratum #830321 |
@@ -314,6 +316,7 @@ | |||
314 | @ after ldm {}^ | 316 | @ after ldm {}^ |
315 | add sp, sp, #\offset + PT_REGS_SIZE | 317 | add sp, sp, #\offset + PT_REGS_SIZE |
316 | movs pc, lr @ return & move spsr_svc into cpsr | 318 | movs pc, lr @ return & move spsr_svc into cpsr |
319 | 1: bug "Returning to usermode but unexpected PSR bits set?", \@ | ||
317 | #elif defined(CONFIG_CPU_V7M) | 320 | #elif defined(CONFIG_CPU_V7M) |
318 | @ V7M restore. | 321 | @ V7M restore. |
319 | @ Note that we don't need to do clrex here as clearing the local | 322 | @ Note that we don't need to do clrex here as clearing the local |
@@ -329,6 +332,8 @@ | |||
329 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr | 332 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr |
330 | ldr lr, [sp, #\offset + S_PC] @ get pc | 333 | ldr lr, [sp, #\offset + S_PC] @ get pc |
331 | add sp, sp, #\offset + S_SP | 334 | add sp, sp, #\offset + S_SP |
335 | tst r1, #0xcf | ||
336 | bne 1f | ||
332 | msr spsr_cxsf, r1 @ save in spsr_svc | 337 | msr spsr_cxsf, r1 @ save in spsr_svc |
333 | 338 | ||
334 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | 339 | @ We must avoid clrex due to Cortex-A15 erratum #830321 |
@@ -341,6 +346,7 @@ | |||
341 | .endif | 346 | .endif |
342 | add sp, sp, #PT_REGS_SIZE - S_SP | 347 | add sp, sp, #PT_REGS_SIZE - S_SP |
343 | movs pc, lr @ return & move spsr_svc into cpsr | 348 | movs pc, lr @ return & move spsr_svc into cpsr |
349 | 1: bug "Returning to usermode but unexpected PSR bits set?", \@ | ||
344 | #endif /* !CONFIG_THUMB2_KERNEL */ | 350 | #endif /* !CONFIG_THUMB2_KERNEL */ |
345 | .endm | 351 | .endm |
346 | 352 | ||
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c index 35ff45470dbf..fc3b44028cfb 100644 --- a/arch/arm/mm/dump.c +++ b/arch/arm/mm/dump.c | |||
@@ -129,8 +129,8 @@ static const struct prot_bits section_bits[] = { | |||
129 | .val = PMD_SECT_USER, | 129 | .val = PMD_SECT_USER, |
130 | .set = "USR", | 130 | .set = "USR", |
131 | }, { | 131 | }, { |
132 | .mask = L_PMD_SECT_RDONLY, | 132 | .mask = L_PMD_SECT_RDONLY | PMD_SECT_AP2, |
133 | .val = L_PMD_SECT_RDONLY, | 133 | .val = L_PMD_SECT_RDONLY | PMD_SECT_AP2, |
134 | .set = "ro", | 134 | .set = "ro", |
135 | .clear = "RW", | 135 | .clear = "RW", |
136 | #elif __LINUX_ARM_ARCH__ >= 6 | 136 | #elif __LINUX_ARM_ARCH__ >= 6 |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 81d4482b6861..a1f11a7ee81b 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -629,8 +629,8 @@ static struct section_perm ro_perms[] = { | |||
629 | .start = (unsigned long)_stext, | 629 | .start = (unsigned long)_stext, |
630 | .end = (unsigned long)__init_begin, | 630 | .end = (unsigned long)__init_begin, |
631 | #ifdef CONFIG_ARM_LPAE | 631 | #ifdef CONFIG_ARM_LPAE |
632 | .mask = ~L_PMD_SECT_RDONLY, | 632 | .mask = ~(L_PMD_SECT_RDONLY | PMD_SECT_AP2), |
633 | .prot = L_PMD_SECT_RDONLY, | 633 | .prot = L_PMD_SECT_RDONLY | PMD_SECT_AP2, |
634 | #else | 634 | #else |
635 | .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE), | 635 | .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE), |
636 | .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, | 636 | .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, |