Merge branch 'devel-stable' into for-next
This commit is contained in:
@@ -87,6 +87,11 @@ head-y := head$(MMUEXT).o
|
||||
obj-$(CONFIG_DEBUG_LL) += debug.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
# This is executed very early using a temporary stack when no memory allocator
|
||||
# nor global data is available. Everything has to be allocated on the stack.
|
||||
CFLAGS_head-inflate-data.o := $(call cc-option,-Wframe-larger-than=10240)
|
||||
obj-$(CONFIG_XIP_DEFLATED_DATA) += head-inflate-data.o
|
||||
|
||||
obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o
|
||||
AFLAGS_hyp-stub.o :=-Wa,-march=armv7-a
|
||||
ifeq ($(CONFIG_ARM_PSCI),y)
|
||||
|
@@ -23,11 +23,13 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/mpu.h>
|
||||
#include <asm/procinfo.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <linux/kbuild.h>
|
||||
#include "signal.h"
|
||||
|
||||
/*
|
||||
* Make sure that the compiler and target are compatible.
|
||||
@@ -112,6 +114,9 @@ int main(void)
|
||||
DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit));
|
||||
DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs));
|
||||
BLANK();
|
||||
DEFINE(SIGFRAME_RC3_OFFSET, offsetof(struct sigframe, retcode[3]));
|
||||
DEFINE(RT_SIGFRAME_RC3_OFFSET, offsetof(struct rt_sigframe, sig.retcode[3]));
|
||||
BLANK();
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base));
|
||||
DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl));
|
||||
@@ -182,6 +187,16 @@ int main(void)
|
||||
BLANK();
|
||||
#ifdef CONFIG_VDSO
|
||||
DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store));
|
||||
#endif
|
||||
BLANK();
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
DEFINE(MPU_RNG_INFO_RNGS, offsetof(struct mpu_rgn_info, rgns));
|
||||
DEFINE(MPU_RNG_INFO_USED, offsetof(struct mpu_rgn_info, used));
|
||||
|
||||
DEFINE(MPU_RNG_SIZE, sizeof(struct mpu_rgn));
|
||||
DEFINE(MPU_RGN_DRBAR, offsetof(struct mpu_rgn, drbar));
|
||||
DEFINE(MPU_RGN_DRSR, offsetof(struct mpu_rgn, drsr));
|
||||
DEFINE(MPU_RGN_DRACR, offsetof(struct mpu_rgn, dracr));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <linux/personality.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/elf-fdpic.h>
|
||||
#include <asm/system_info.h>
|
||||
|
||||
int elf_check_arch(const struct elf32_hdr *x)
|
||||
@@ -80,7 +81,7 @@ EXPORT_SYMBOL(elf_set_personality);
|
||||
* - the binary requires an executable stack
|
||||
* - we're running on a CPU which doesn't support NX.
|
||||
*/
|
||||
int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
|
||||
int arm_elf_read_implies_exec(int executable_stack)
|
||||
{
|
||||
if (executable_stack != EXSTACK_DISABLE_X)
|
||||
return 1;
|
||||
@@ -89,3 +90,24 @@ int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(arm_elf_read_implies_exec);
|
||||
|
||||
#if defined(CONFIG_MMU) && defined(CONFIG_BINFMT_ELF_FDPIC)
|
||||
|
||||
void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
|
||||
struct elf_fdpic_params *interp_params,
|
||||
unsigned long *start_stack,
|
||||
unsigned long *start_brk)
|
||||
{
|
||||
elf_set_personality(&exec_params->hdr);
|
||||
|
||||
exec_params->load_addr = 0x8000;
|
||||
interp_params->load_addr = ELF_ET_DYN_BASE;
|
||||
*start_stack = TASK_SIZE - SZ_16M;
|
||||
|
||||
if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_INDEPENDENT) {
|
||||
exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
|
||||
exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -79,47 +79,69 @@ ENDPROC(__vet_atags)
|
||||
*/
|
||||
__INIT
|
||||
__mmap_switched:
|
||||
adr r3, __mmap_switched_data
|
||||
|
||||
ldmia r3!, {r4, r5, r6, r7}
|
||||
cmp r4, r5 @ Copy data segment if needed
|
||||
1: cmpne r5, r6
|
||||
ldrne fp, [r4], #4
|
||||
strne fp, [r5], #4
|
||||
bne 1b
|
||||
mov r7, r1
|
||||
mov r8, r2
|
||||
mov r10, r0
|
||||
|
||||
mov fp, #0 @ Clear BSS (and zero fp)
|
||||
1: cmp r6, r7
|
||||
strcc fp, [r6],#4
|
||||
bcc 1b
|
||||
adr r4, __mmap_switched_data
|
||||
mov fp, #0
|
||||
|
||||
ARM( ldmia r3, {r4, r5, r6, r7, sp})
|
||||
THUMB( ldmia r3, {r4, r5, r6, r7} )
|
||||
THUMB( ldr sp, [r3, #16] )
|
||||
str r9, [r4] @ Save processor ID
|
||||
str r1, [r5] @ Save machine type
|
||||
str r2, [r6] @ Save atags pointer
|
||||
cmp r7, #0
|
||||
strne r0, [r7] @ Save control register values
|
||||
#if defined(CONFIG_XIP_DEFLATED_DATA)
|
||||
ARM( ldr sp, [r4], #4 )
|
||||
THUMB( ldr sp, [r4] )
|
||||
THUMB( add r4, #4 )
|
||||
bl __inflate_kernel_data @ decompress .data to RAM
|
||||
teq r0, #0
|
||||
bne __error
|
||||
#elif defined(CONFIG_XIP_KERNEL)
|
||||
ARM( ldmia r4!, {r0, r1, r2, sp} )
|
||||
THUMB( ldmia r4!, {r0, r1, r2, r3} )
|
||||
THUMB( mov sp, r3 )
|
||||
sub r2, r2, r1
|
||||
bl memcpy @ copy .data to RAM
|
||||
#endif
|
||||
|
||||
ARM( ldmia r4!, {r0, r1, sp} )
|
||||
THUMB( ldmia r4!, {r0, r1, r3} )
|
||||
THUMB( mov sp, r3 )
|
||||
sub r1, r1, r0
|
||||
bl __memzero @ clear .bss
|
||||
|
||||
ldmia r4, {r0, r1, r2, r3}
|
||||
str r9, [r0] @ Save processor ID
|
||||
str r7, [r1] @ Save machine type
|
||||
str r8, [r2] @ Save atags pointer
|
||||
cmp r3, #0
|
||||
strne r10, [r3] @ Save control register values
|
||||
mov lr, #0
|
||||
b start_kernel
|
||||
ENDPROC(__mmap_switched)
|
||||
|
||||
.align 2
|
||||
.type __mmap_switched_data, %object
|
||||
__mmap_switched_data:
|
||||
.long __data_loc @ r4
|
||||
.long _sdata @ r5
|
||||
.long __bss_start @ r6
|
||||
.long _end @ r7
|
||||
.long processor_id @ r4
|
||||
.long __machine_arch_type @ r5
|
||||
.long __atags_pointer @ r6
|
||||
#ifdef CONFIG_CPU_CP15
|
||||
.long cr_alignment @ r7
|
||||
#else
|
||||
.long 0 @ r7
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#ifndef CONFIG_XIP_DEFLATED_DATA
|
||||
.long _sdata @ r0
|
||||
.long __data_loc @ r1
|
||||
.long _edata_loc @ r2
|
||||
#endif
|
||||
.long __bss_stop @ sp (temporary stack in .bss)
|
||||
#endif
|
||||
|
||||
.long __bss_start @ r0
|
||||
.long __bss_stop @ r1
|
||||
.long init_thread_union + THREAD_START_SP @ sp
|
||||
|
||||
.long processor_id @ r0
|
||||
.long __machine_arch_type @ r1
|
||||
.long __atags_pointer @ r2
|
||||
#ifdef CONFIG_CPU_CP15
|
||||
.long cr_alignment @ r3
|
||||
#else
|
||||
.long 0 @ r3
|
||||
#endif
|
||||
.size __mmap_switched_data, . - __mmap_switched_data
|
||||
|
||||
/*
|
||||
|
62
arch/arm/kernel/head-inflate-data.c
Normal file
62
arch/arm/kernel/head-inflate-data.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* XIP kernel .data segment decompressor
|
||||
*
|
||||
* Created by: Nicolas Pitre, August 2017
|
||||
* Copyright: (C) 2017 Linaro 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 <linux/init.h>
|
||||
#include <linux/zutil.h>
|
||||
|
||||
/* for struct inflate_state */
|
||||
#include "../../../lib/zlib_inflate/inftrees.h"
|
||||
#include "../../../lib/zlib_inflate/inflate.h"
|
||||
#include "../../../lib/zlib_inflate/infutil.h"
|
||||
|
||||
extern char __data_loc[];
|
||||
extern char _edata_loc[];
|
||||
extern char _sdata[];
|
||||
|
||||
/*
|
||||
* This code is called very early during the boot process to decompress
|
||||
* the .data segment stored compressed in ROM. Therefore none of the global
|
||||
* variables are valid yet, hence no kernel services such as memory
|
||||
* allocation is available. Everything must be allocated on the stack and
|
||||
* we must avoid any global data access. We use a temporary stack located
|
||||
* in the .bss area. The linker script makes sure the .bss is big enough
|
||||
* to hold our stack frame plus some room for called functions.
|
||||
*
|
||||
* We mimic the code in lib/decompress_inflate.c to use the smallest work
|
||||
* area possible. And because everything is statically allocated on the
|
||||
* stack then there is no need to clean up before returning.
|
||||
*/
|
||||
|
||||
int __init __inflate_kernel_data(void)
|
||||
{
|
||||
struct z_stream_s stream, *strm = &stream;
|
||||
struct inflate_state state;
|
||||
char *in = __data_loc;
|
||||
int rc;
|
||||
|
||||
/* Check and skip gzip header (assume no filename) */
|
||||
if (in[0] != 0x1f || in[1] != 0x8b || in[2] != 0x08 || in[3] & ~3)
|
||||
return -1;
|
||||
in += 10;
|
||||
|
||||
strm->workspace = &state;
|
||||
strm->next_in = in;
|
||||
strm->avail_in = _edata_loc - __data_loc; /* upper bound */
|
||||
strm->next_out = _sdata;
|
||||
strm->avail_out = _edata_loc - __data_loc;
|
||||
zlib_inflateInit2(strm, -MAX_WBITS);
|
||||
WS(strm)->inflate_state.wsize = 0;
|
||||
WS(strm)->inflate_state.window = NULL;
|
||||
rc = zlib_inflate(strm, Z_FINISH);
|
||||
if (rc == Z_OK || rc == Z_STREAM_END)
|
||||
rc = strm->avail_out; /* should be 0 */
|
||||
return rc;
|
||||
}
|
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/ptrace.h>
|
||||
@@ -110,8 +111,8 @@ ENTRY(secondary_startup)
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
/* Use MPU region info supplied by __cpu_up */
|
||||
ldr r6, [r7] @ get secondary_data.mpu_szr
|
||||
bl __setup_mpu @ Initialize the MPU
|
||||
ldr r6, [r7] @ get secondary_data.mpu_rgn_info
|
||||
bl __secondary_setup_mpu @ Initialize the MPU
|
||||
#endif
|
||||
|
||||
badr lr, 1f @ return (PIC) address
|
||||
@@ -175,19 +176,33 @@ ENDPROC(__after_proc_init)
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
|
||||
|
||||
#ifndef CONFIG_CPU_V7M
|
||||
/* Set which MPU region should be programmed */
|
||||
.macro set_region_nr tmp, rgnr
|
||||
.macro set_region_nr tmp, rgnr, unused
|
||||
mov \tmp, \rgnr @ Use static region numbers
|
||||
mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR
|
||||
.endm
|
||||
|
||||
/* Setup a single MPU region, either D or I side (D-side for unified) */
|
||||
.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE
|
||||
.macro setup_region bar, acr, sr, side = MPU_DATA_SIDE, unused
|
||||
mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR
|
||||
mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR
|
||||
mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR
|
||||
.endm
|
||||
#else
|
||||
.macro set_region_nr tmp, rgnr, base
|
||||
mov \tmp, \rgnr
|
||||
str \tmp, [\base, #MPU_RNR]
|
||||
.endm
|
||||
|
||||
.macro setup_region bar, acr, sr, unused, base
|
||||
lsl \acr, \acr, #16
|
||||
orr \acr, \acr, \sr
|
||||
str \bar, [\base, #MPU_RBAR]
|
||||
str \acr, [\base, #MPU_RASR]
|
||||
.endm
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Setup the MPU and initial MPU Regions. We create the following regions:
|
||||
* Region 0: Use this for probing the MPU details, so leave disabled.
|
||||
@@ -201,64 +216,137 @@ ENDPROC(__after_proc_init)
|
||||
ENTRY(__setup_mpu)
|
||||
|
||||
/* Probe for v7 PMSA compliance */
|
||||
mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0
|
||||
M_CLASS(movw r12, #:lower16:BASEADDR_V7M_SCB)
|
||||
M_CLASS(movt r12, #:upper16:BASEADDR_V7M_SCB)
|
||||
|
||||
AR_CLASS(mrc p15, 0, r0, c0, c1, 4) @ Read ID_MMFR0
|
||||
M_CLASS(ldr r0, [r12, 0x50])
|
||||
and r0, r0, #(MMFR0_PMSA) @ PMSA field
|
||||
teq r0, #(MMFR0_PMSAv7) @ PMSA v7
|
||||
bne __error_p @ Fail: ARM_MPU on NOT v7 PMSA
|
||||
bxne lr
|
||||
|
||||
/* Determine whether the D/I-side memory map is unified. We set the
|
||||
* flags here and continue to use them for the rest of this function */
|
||||
mrc p15, 0, r0, c0, c0, 4 @ MPUIR
|
||||
AR_CLASS(mrc p15, 0, r0, c0, c0, 4) @ MPUIR
|
||||
M_CLASS(ldr r0, [r12, #MPU_TYPE])
|
||||
ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
|
||||
beq __error_p @ Fail: ARM_MPU and no MPU
|
||||
bxeq lr
|
||||
tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
|
||||
|
||||
/* Setup second region first to free up r6 */
|
||||
set_region_nr r0, #MPU_RAM_REGION
|
||||
set_region_nr r0, #MPU_RAM_REGION, r12
|
||||
isb
|
||||
/* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
|
||||
ldr r0, =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET
|
||||
ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE @ PHYS_OFFSET, shared, enabled
|
||||
beq 1f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ PHYS_OFFSET, shared, enabled
|
||||
beq 1f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ PHYS_OFFSET, shared, enabled
|
||||
1: isb
|
||||
|
||||
/* First/background region */
|
||||
set_region_nr r0, #MPU_BG_REGION
|
||||
set_region_nr r0, #MPU_BG_REGION, r12
|
||||
isb
|
||||
/* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
|
||||
mov r0, #0 @ BG region starts at 0x0
|
||||
ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA)
|
||||
mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE @ 0x0, BG region, enabled
|
||||
beq 2f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ 0x0, BG region, enabled
|
||||
beq 2f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE r12 @ 0x0, BG region, enabled
|
||||
2: isb
|
||||
|
||||
/* Vectors region */
|
||||
set_region_nr r0, #MPU_VECTORS_REGION
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
set_region_nr r0, #MPU_ROM_REGION, r12
|
||||
isb
|
||||
/* Shared, inaccessible to PL0, rw PL1 */
|
||||
mov r0, #CONFIG_VECTORS_BASE @ Cover from VECTORS_BASE
|
||||
ldr r5,=(MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL)
|
||||
/* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */
|
||||
mov r6, #(((2 * PAGE_SHIFT - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN)
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE @ VECTORS_BASE, PL0 NA, enabled
|
||||
beq 3f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE @ VECTORS_BASE, PL0 NA, enabled
|
||||
ldr r5,=(MPU_AP_PL1RO_PL0NA | MPU_RGN_NORMAL)
|
||||
|
||||
ldr r0, =CONFIG_XIP_PHYS_ADDR @ ROM start
|
||||
ldr r6, =(_exiprom) @ ROM end
|
||||
sub r6, r6, r0 @ Minimum size of region to map
|
||||
clz r6, r6 @ Region size must be 2^N...
|
||||
rsb r6, r6, #31 @ ...so round up region size
|
||||
lsl r6, r6, #MPU_RSR_SZ @ Put size in right field
|
||||
orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled
|
||||
beq 3f @ Memory-map not unified
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled
|
||||
3: isb
|
||||
#endif
|
||||
|
||||
/* Enable the MPU */
|
||||
AR_CLASS(mrc p15, 0, r0, c1, c0, 0) @ Read SCTLR
|
||||
AR_CLASS(bic r0, r0, #CR_BR) @ Disable the 'default mem-map'
|
||||
AR_CLASS(orr r0, r0, #CR_M) @ Set SCTRL.M (MPU on)
|
||||
AR_CLASS(mcr p15, 0, r0, c1, c0, 0) @ Enable MPU
|
||||
|
||||
M_CLASS(ldr r0, [r12, #MPU_CTRL])
|
||||
M_CLASS(bic r0, #MPU_CTRL_PRIVDEFENA)
|
||||
M_CLASS(orr r0, #MPU_CTRL_ENABLE)
|
||||
M_CLASS(str r0, [r12, #MPU_CTRL])
|
||||
isb
|
||||
|
||||
ret lr
|
||||
ENDPROC(__setup_mpu)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* r6: pointer at mpu_rgn_info
|
||||
*/
|
||||
|
||||
ENTRY(__secondary_setup_mpu)
|
||||
/* Probe for v7 PMSA compliance */
|
||||
mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0
|
||||
and r0, r0, #(MMFR0_PMSA) @ PMSA field
|
||||
teq r0, #(MMFR0_PMSAv7) @ PMSA v7
|
||||
bne __error_p
|
||||
|
||||
/* Determine whether the D/I-side memory map is unified. We set the
|
||||
* flags here and continue to use them for the rest of this function */
|
||||
mrc p15, 0, r0, c0, c0, 4 @ MPUIR
|
||||
ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
|
||||
beq __error_p
|
||||
|
||||
ldr r4, [r6, #MPU_RNG_INFO_USED]
|
||||
mov r5, #MPU_RNG_SIZE
|
||||
add r3, r6, #MPU_RNG_INFO_RNGS
|
||||
mla r3, r4, r5, r3
|
||||
|
||||
1:
|
||||
tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
|
||||
sub r3, r3, #MPU_RNG_SIZE
|
||||
sub r4, r4, #1
|
||||
|
||||
set_region_nr r0, r4
|
||||
isb
|
||||
|
||||
ldr r0, [r3, #MPU_RGN_DRBAR]
|
||||
ldr r6, [r3, #MPU_RGN_DRSR]
|
||||
ldr r5, [r3, #MPU_RGN_DRACR]
|
||||
|
||||
setup_region r0, r5, r6, MPU_DATA_SIDE
|
||||
beq 2f
|
||||
setup_region r0, r5, r6, MPU_INSTR_SIDE
|
||||
2: isb
|
||||
|
||||
mrc p15, 0, r0, c0, c0, 4 @ Reevaluate the MPUIR
|
||||
cmp r4, #0
|
||||
bgt 1b
|
||||
|
||||
/* Enable the MPU */
|
||||
mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
|
||||
bic r0, r0, #CR_BR @ Disable the 'default mem-map'
|
||||
bic r0, r0, #CR_BR @ Disable the 'default mem-map'
|
||||
orr r0, r0, #CR_M @ Set SCTRL.M (MPU on)
|
||||
mcr p15, 0, r0, c1, c0, 0 @ Enable MPU
|
||||
isb
|
||||
|
||||
ret lr
|
||||
ENDPROC(__setup_mpu)
|
||||
#endif
|
||||
ENDPROC(__secondary_setup_mpu)
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
#endif /* CONFIG_ARM_MPU */
|
||||
#include "head-common.S"
|
||||
|
@@ -19,11 +19,12 @@
|
||||
#include <asm/elf.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/ucontext.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/vfp.h>
|
||||
|
||||
extern const unsigned long sigreturn_codes[7];
|
||||
#include "signal.h"
|
||||
|
||||
extern const unsigned long sigreturn_codes[17];
|
||||
|
||||
static unsigned long signal_return_offset;
|
||||
|
||||
@@ -172,15 +173,6 @@ static int restore_vfp_context(char __user **auxp)
|
||||
/*
|
||||
* Do a signal return; undo the signal stack. These are aligned to 64-bit.
|
||||
*/
|
||||
struct sigframe {
|
||||
struct ucontext uc;
|
||||
unsigned long retcode[2];
|
||||
};
|
||||
|
||||
struct rt_sigframe {
|
||||
struct siginfo info;
|
||||
struct sigframe sig;
|
||||
};
|
||||
|
||||
static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
|
||||
{
|
||||
@@ -366,9 +358,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||
unsigned long __user *rc, void __user *frame)
|
||||
{
|
||||
unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
unsigned long handler_fdpic_GOT = 0;
|
||||
unsigned long retcode;
|
||||
int thumb = 0;
|
||||
unsigned int idx, thumb = 0;
|
||||
unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
|
||||
bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
|
||||
(current->personality & FDPIC_FUNCPTRS);
|
||||
|
||||
if (fdpic) {
|
||||
unsigned long __user *fdpic_func_desc =
|
||||
(unsigned long __user *)handler;
|
||||
if (__get_user(handler, &fdpic_func_desc[0]) ||
|
||||
__get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
|
||||
return 1;
|
||||
}
|
||||
|
||||
cpsr |= PSR_ENDSTATE;
|
||||
|
||||
@@ -408,9 +411,26 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
retcode = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
if (fdpic) {
|
||||
/*
|
||||
* We need code to load the function descriptor.
|
||||
* That code follows the standard sigreturn code
|
||||
* (6 words), and is made of 3 + 2 words for each
|
||||
* variant. The 4th copied word is the actual FD
|
||||
* address that the assembly code expects.
|
||||
*/
|
||||
idx = 6 + thumb * 3;
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
idx += 5;
|
||||
if (__put_user(sigreturn_codes[idx], rc ) ||
|
||||
__put_user(sigreturn_codes[idx+1], rc+1) ||
|
||||
__put_user(sigreturn_codes[idx+2], rc+2) ||
|
||||
__put_user(retcode, rc+3))
|
||||
return 1;
|
||||
goto rc_finish;
|
||||
}
|
||||
} else {
|
||||
unsigned int idx = thumb << 1;
|
||||
|
||||
idx = thumb << 1;
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
idx += 3;
|
||||
|
||||
@@ -422,6 +442,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||
__put_user(sigreturn_codes[idx+1], rc+1))
|
||||
return 1;
|
||||
|
||||
rc_finish:
|
||||
#ifdef CONFIG_MMU
|
||||
if (cpsr & MODE32_BIT) {
|
||||
struct mm_struct *mm = current->mm;
|
||||
@@ -441,7 +462,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||
* the return code written onto the stack.
|
||||
*/
|
||||
flush_icache_range((unsigned long)rc,
|
||||
(unsigned long)(rc + 2));
|
||||
(unsigned long)(rc + 3));
|
||||
|
||||
retcode = ((unsigned long)rc) + thumb;
|
||||
}
|
||||
@@ -451,6 +472,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
|
||||
regs->ARM_sp = (unsigned long)frame;
|
||||
regs->ARM_lr = retcode;
|
||||
regs->ARM_pc = handler;
|
||||
if (fdpic)
|
||||
regs->ARM_r9 = handler_fdpic_GOT;
|
||||
regs->ARM_cpsr = cpsr;
|
||||
|
||||
return 0;
|
||||
|
11
arch/arm/kernel/signal.h
Normal file
11
arch/arm/kernel/signal.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <asm/ucontext.h>
|
||||
|
||||
struct sigframe {
|
||||
struct ucontext uc;
|
||||
unsigned long retcode[4];
|
||||
};
|
||||
|
||||
struct rt_sigframe {
|
||||
struct siginfo info;
|
||||
struct sigframe sig;
|
||||
};
|
@@ -14,6 +14,8 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/*
|
||||
@@ -51,6 +53,17 @@ ARM_OK( .arm )
|
||||
.thumb
|
||||
.endm
|
||||
|
||||
.macro arm_fdpic_slot n
|
||||
.org sigreturn_codes + 24 + 20 * (\n)
|
||||
ARM_OK( .arm )
|
||||
.endm
|
||||
|
||||
.macro thumb_fdpic_slot n
|
||||
.org sigreturn_codes + 24 + 20 * (\n) + 12
|
||||
.thumb
|
||||
.endm
|
||||
|
||||
|
||||
#if __LINUX_ARM_ARCH__ <= 4
|
||||
/*
|
||||
* Note we manually set minimally required arch that supports
|
||||
@@ -90,13 +103,46 @@ ARM_OK( swi #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE) )
|
||||
movs r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
|
||||
swi #0
|
||||
|
||||
/* ARM sigreturn restorer FDPIC bounce code snippet */
|
||||
arm_fdpic_slot 0
|
||||
ARM_OK( ldr r3, [sp, #SIGFRAME_RC3_OFFSET] )
|
||||
ARM_OK( ldmia r3, {r3, r9} )
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
ARM_OK( bx r3 )
|
||||
#else
|
||||
ARM_OK( ret r3 )
|
||||
#endif
|
||||
|
||||
/* Thumb sigreturn restorer FDPIC bounce code snippet */
|
||||
thumb_fdpic_slot 0
|
||||
ldr r3, [sp, #SIGFRAME_RC3_OFFSET]
|
||||
ldmia r3, {r2, r3}
|
||||
mov r9, r3
|
||||
bx r2
|
||||
|
||||
/* ARM sigreturn_rt restorer FDPIC bounce code snippet */
|
||||
arm_fdpic_slot 1
|
||||
ARM_OK( ldr r3, [sp, #RT_SIGFRAME_RC3_OFFSET] )
|
||||
ARM_OK( ldmia r3, {r3, r9} )
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
ARM_OK( bx r3 )
|
||||
#else
|
||||
ARM_OK( ret r3 )
|
||||
#endif
|
||||
|
||||
/* Thumb sigreturn_rt restorer FDPIC bounce code snippet */
|
||||
thumb_fdpic_slot 1
|
||||
ldr r3, [sp, #RT_SIGFRAME_RC3_OFFSET]
|
||||
ldmia r3, {r2, r3}
|
||||
mov r9, r3
|
||||
bx r2
|
||||
|
||||
/*
|
||||
* Note on addtional space: setup_return in signal.c
|
||||
* algorithm uses two words copy regardless whether
|
||||
* it is thumb case or not, so we need additional
|
||||
* word after real last entry.
|
||||
* Note on additional space: setup_return in signal.c
|
||||
* always copies the same number of words regardless whether
|
||||
* it is thumb case or not, so we need one additional padding
|
||||
* word after the last entry.
|
||||
*/
|
||||
arm_slot 2
|
||||
.space 4
|
||||
|
||||
.size sigreturn_codes, . - sigreturn_codes
|
||||
|
@@ -114,7 +114,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||
*/
|
||||
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
secondary_data.mpu_rgn_szr = mpu_rgn_info.rgns[MPU_RAM_REGION].drsr;
|
||||
secondary_data.mpu_rgn_info = &mpu_rgn_info;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
@@ -655,6 +655,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
|
||||
set_tls(regs->ARM_r0);
|
||||
return 0;
|
||||
|
||||
case NR(get_tls):
|
||||
return current_thread_info()->tp_value[0];
|
||||
|
||||
default:
|
||||
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
|
||||
if not implemented, rather than raising SIGILL. This
|
||||
|
@@ -6,6 +6,8 @@
|
||||
/* No __ro_after_init data in the .rodata section - which will always be ro */
|
||||
#define RO_AFTER_INIT_DATA
|
||||
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <asm-generic/vmlinux.lds.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/thread_info.h>
|
||||
@@ -77,9 +79,7 @@ SECTIONS
|
||||
*(.text.fixup)
|
||||
*(__ex_table)
|
||||
#endif
|
||||
#ifndef CONFIG_SMP_ON_UP
|
||||
*(.alt.smp.init)
|
||||
#endif
|
||||
*(.discard)
|
||||
*(.discard.*)
|
||||
}
|
||||
@@ -181,19 +181,7 @@ SECTIONS
|
||||
*(.taglist.init)
|
||||
__tagtable_end = .;
|
||||
}
|
||||
#ifdef CONFIG_SMP_ON_UP
|
||||
.init.smpalt : {
|
||||
__smpalt_begin = .;
|
||||
*(.alt.smp.init)
|
||||
__smpalt_end = .;
|
||||
}
|
||||
#endif
|
||||
.init.pv_table : {
|
||||
__pv_table_begin = .;
|
||||
*(.pv_table)
|
||||
__pv_table_end = .;
|
||||
}
|
||||
.init.data : {
|
||||
.init.rodata : {
|
||||
INIT_SETUP(16)
|
||||
INIT_CALLS
|
||||
CON_INITCALL
|
||||
@@ -201,48 +189,49 @@ SECTIONS
|
||||
INIT_RAM_FS
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
. = ALIGN(SZ_128K);
|
||||
#endif
|
||||
_exiprom = .; /* End of XIP ROM area */
|
||||
|
||||
/*
|
||||
* From this point, stuff is considered writable and will be copied to RAM
|
||||
*/
|
||||
__data_loc = ALIGN(4); /* location in file */
|
||||
. = PAGE_OFFSET + TEXT_OFFSET; /* location in memory */
|
||||
#undef LOAD_OFFSET
|
||||
#define LOAD_OFFSET (PAGE_OFFSET + TEXT_OFFSET - __data_loc)
|
||||
|
||||
. = ALIGN(THREAD_SIZE);
|
||||
_sdata = .;
|
||||
RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
|
||||
.data.ro_after_init : AT(ADDR(.data.ro_after_init) - LOAD_OFFSET) {
|
||||
*(.data..ro_after_init)
|
||||
}
|
||||
_edata = .;
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__init_begin = .;
|
||||
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
|
||||
INIT_DATA
|
||||
}
|
||||
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
|
||||
ARM_EXIT_KEEP(EXIT_DATA)
|
||||
}
|
||||
#ifdef CONFIG_SMP
|
||||
PERCPU_SECTION(L1_CACHE_BYTES)
|
||||
#endif
|
||||
|
||||
_exiprom = .; /* End of XIP ROM area */
|
||||
__data_loc = ALIGN(4); /* location in binary */
|
||||
. = PAGE_OFFSET + TEXT_OFFSET;
|
||||
/*
|
||||
* End of copied data. We need a dummy section to get its LMA.
|
||||
* Also located before final ALIGN() as trailing padding is not stored
|
||||
* in the resulting binary file and useless to copy.
|
||||
*/
|
||||
.data.endmark : AT(ADDR(.data.endmark) - LOAD_OFFSET) { }
|
||||
_edata_loc = LOADADDR(.data.endmark);
|
||||
|
||||
.data : AT(__data_loc) {
|
||||
_data = .; /* address in memory */
|
||||
_sdata = .;
|
||||
|
||||
/*
|
||||
* first, the init task union, aligned
|
||||
* to an 8192 byte boundary.
|
||||
*/
|
||||
INIT_TASK_DATA(THREAD_SIZE)
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__init_begin = .;
|
||||
INIT_DATA
|
||||
ARM_EXIT_KEEP(EXIT_DATA)
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__init_end = .;
|
||||
|
||||
*(.data..ro_after_init)
|
||||
|
||||
NOSAVE_DATA
|
||||
CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
|
||||
READ_MOSTLY_DATA(L1_CACHE_BYTES)
|
||||
|
||||
/*
|
||||
* and the usual data section
|
||||
*/
|
||||
DATA_DATA
|
||||
CONSTRUCTORS
|
||||
|
||||
_edata = .;
|
||||
}
|
||||
_edata_loc = __data_loc + SIZEOF(.data);
|
||||
|
||||
BUG_TABLE
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__init_end = .;
|
||||
|
||||
#ifdef CONFIG_HAVE_TCM
|
||||
/*
|
||||
@@ -301,7 +290,7 @@ SECTIONS
|
||||
}
|
||||
#endif
|
||||
|
||||
BSS_SECTION(0, 0, 0)
|
||||
BSS_SECTION(0, 0, 8)
|
||||
_end = .;
|
||||
|
||||
STABS_DEBUG
|
||||
@@ -322,3 +311,29 @@ ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
|
||||
*/
|
||||
ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE,
|
||||
"HYP init code too big or misaligned")
|
||||
|
||||
#ifdef CONFIG_XIP_DEFLATED_DATA
|
||||
/*
|
||||
* The .bss is used as a stack area for __inflate_kernel_data() whose stack
|
||||
* frame is 9568 bytes. Make sure it has extra room left.
|
||||
*/
|
||||
ASSERT((_end - __bss_start) >= 12288, ".bss too small for CONFIG_XIP_DEFLATED_DATA")
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
/*
|
||||
* Due to PMSAv7 restriction on base address and size we have to
|
||||
* enforce minimal alignment restrictions. It was seen that weaker
|
||||
* alignment restriction on _xiprom will likely force XIP address
|
||||
* space spawns multiple MPU regions thus it is likely we run in
|
||||
* situation when we are reprogramming MPU region we run on with
|
||||
* something which doesn't cover reprogramming code itself, so as soon
|
||||
* as we update MPU settings we'd immediately try to execute straight
|
||||
* from background region which is XN.
|
||||
* It seem that alignment in 1M should suit most users.
|
||||
* _exiprom is aligned as 1/8 of 1M so can be covered by subregion
|
||||
* disable
|
||||
*/
|
||||
ASSERT(!(_xiprom & (SZ_1M - 1)), "XIP start address may cause MPU programming issues")
|
||||
ASSERT(!(_exiprom & (SZ_128K - 1)), "XIP end address may cause MPU programming issues")
|
||||
#endif
|
||||
|
@@ -214,14 +214,9 @@ SECTIONS
|
||||
*(.pv_table)
|
||||
__pv_table_end = .;
|
||||
}
|
||||
.init.data : {
|
||||
INIT_DATA
|
||||
INIT_SETUP(16)
|
||||
INIT_CALLS
|
||||
CON_INITCALL
|
||||
SECURITY_INITCALL
|
||||
INIT_RAM_FS
|
||||
}
|
||||
|
||||
INIT_DATA_SECTION(16)
|
||||
|
||||
.exit.data : {
|
||||
ARM_EXIT_KEEP(EXIT_DATA)
|
||||
}
|
||||
@@ -236,33 +231,10 @@ SECTIONS
|
||||
. = ALIGN(THREAD_SIZE);
|
||||
#endif
|
||||
__init_end = .;
|
||||
__data_loc = .;
|
||||
|
||||
.data : AT(__data_loc) {
|
||||
_data = .; /* address in memory */
|
||||
_sdata = .;
|
||||
|
||||
/*
|
||||
* first, the init task union, aligned
|
||||
* to an 8192 byte boundary.
|
||||
*/
|
||||
INIT_TASK_DATA(THREAD_SIZE)
|
||||
|
||||
NOSAVE_DATA
|
||||
CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
|
||||
READ_MOSTLY_DATA(L1_CACHE_BYTES)
|
||||
|
||||
/*
|
||||
* and the usual data section
|
||||
*/
|
||||
DATA_DATA
|
||||
CONSTRUCTORS
|
||||
|
||||
_edata = .;
|
||||
}
|
||||
_edata_loc = __data_loc + SIZEOF(.data);
|
||||
|
||||
BUG_TABLE
|
||||
_sdata = .;
|
||||
RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
|
||||
_edata = .;
|
||||
|
||||
#ifdef CONFIG_HAVE_TCM
|
||||
/*
|
||||
|
Reference in New Issue
Block a user