Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
02196144
Commit
02196144
authored
Nov 08, 2017
by
Russell King
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'devel-stable' into for-next
parents
7f3d1f98
fe9c0589
Changes
33
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
1137 additions
and
455 deletions
+1137
-455
arch/arm/Kconfig
arch/arm/Kconfig
+11
-9
arch/arm/Kconfig-nommu
arch/arm/Kconfig-nommu
+2
-2
arch/arm/boot/Makefile
arch/arm/boot/Makefile
+12
-1
arch/arm/boot/deflate_xip_data.sh
arch/arm/boot/deflate_xip_data.sh
+64
-0
arch/arm/include/asm/cputype.h
arch/arm/include/asm/cputype.h
+10
-0
arch/arm/include/asm/elf.h
arch/arm/include/asm/elf.h
+14
-2
arch/arm/include/asm/mmu.h
arch/arm/include/asm/mmu.h
+8
-0
arch/arm/include/asm/mpu.h
arch/arm/include/asm/mpu.h
+20
-6
arch/arm/include/asm/processor.h
arch/arm/include/asm/processor.h
+15
-7
arch/arm/include/asm/smp.h
arch/arm/include/asm/smp.h
+1
-1
arch/arm/include/asm/ucontext.h
arch/arm/include/asm/ucontext.h
+1
-0
arch/arm/include/asm/v7m.h
arch/arm/include/asm/v7m.h
+10
-0
arch/arm/include/uapi/asm/ptrace.h
arch/arm/include/uapi/asm/ptrace.h
+4
-0
arch/arm/include/uapi/asm/unistd.h
arch/arm/include/uapi/asm/unistd.h
+1
-0
arch/arm/kernel/Makefile
arch/arm/kernel/Makefile
+5
-0
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/asm-offsets.c
+15
-0
arch/arm/kernel/elf.c
arch/arm/kernel/elf.c
+23
-1
arch/arm/kernel/head-common.S
arch/arm/kernel/head-common.S
+54
-32
arch/arm/kernel/head-inflate-data.c
arch/arm/kernel/head-inflate-data.c
+62
-0
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head-nommu.S
+118
-30
arch/arm/kernel/signal.c
arch/arm/kernel/signal.c
+38
-15
arch/arm/kernel/signal.h
arch/arm/kernel/signal.h
+11
-0
arch/arm/kernel/sigreturn_codes.S
arch/arm/kernel/sigreturn_codes.S
+51
-5
arch/arm/kernel/smp.c
arch/arm/kernel/smp.c
+1
-1
arch/arm/kernel/traps.c
arch/arm/kernel/traps.c
+3
-0
arch/arm/kernel/vmlinux-xip.lds.S
arch/arm/kernel/vmlinux-xip.lds.S
+65
-50
arch/arm/kernel/vmlinux.lds.S
arch/arm/kernel/vmlinux.lds.S
+6
-34
arch/arm/mm/Makefile
arch/arm/mm/Makefile
+1
-0
arch/arm/mm/nommu.c
arch/arm/mm/nommu.c
+1
-253
arch/arm/mm/pmsa-v7.c
arch/arm/mm/pmsa-v7.c
+484
-0
fs/Kconfig.binfmt
fs/Kconfig.binfmt
+2
-2
fs/binfmt_elf.c
fs/binfmt_elf.c
+13
-2
fs/binfmt_elf_fdpic.c
fs/binfmt_elf_fdpic.c
+11
-2
No files found.
arch/arm/Kconfig
View file @
02196144
...
...
@@ -240,15 +240,6 @@ config NEED_RET_TO_USER
config ARCH_MTD_XIP
bool
config VECTORS_BASE
hex
default 0xffff0000 if MMU || CPU_HIGH_VECTOR
default DRAM_BASE if REMAP_VECTORS_TO_RAM
default 0x00000000
help
The base address of exception vectors. This must be two pages
in size.
config ARM_PATCH_PHYS_VIRT
bool "Patch physical to virtual translations at runtime" if EMBEDDED
default y
...
...
@@ -2006,6 +1997,17 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.
config XIP_DEFLATED_DATA
bool "Store kernel .data section compressed in ROM"
depends on XIP_KERNEL
select ZLIB_INFLATE
help
Before the kernel is actually executed, its .data section has to be
copied to RAM from ROM. This option allows for storing that data
in compressed form and decompressed to RAM rather than merely being
copied, saving some precious ROM space. A possible drawback is a
slightly longer boot delay.
config KEXEC
bool "Kexec system call (EXPERIMENTAL)"
depends on (!SMP || PM_SLEEP_SMP)
...
...
arch/arm/Kconfig-nommu
View file @
02196144
...
...
@@ -52,8 +52,8 @@ config REMAP_VECTORS_TO_RAM
config ARM_MPU
bool 'Use the ARM v7 PMSA Compliant MPU'
depends on CPU_V7
default y
depends on CPU_V7
|| CPU_V7M
default y
if CPU_V7
help
Some ARM systems without an MMU have instead a Memory Protection
Unit (MPU) that defines the type and permissions for regions of
...
...
arch/arm/boot/Makefile
View file @
02196144
...
...
@@ -31,8 +31,19 @@ targets := Image zImage xipImage bootpImage uImage
ifeq
($(CONFIG_XIP_KERNEL),y)
cmd_deflate_xip_data
=
$(CONFIG_SHELL)
-c
\
'
$(srctree)
/
$(src)
/deflate_xip_data.sh $< $@ || { rm -f $@; false; }'
ifeq
($(CONFIG_XIP_DEFLATED_DATA),y)
quiet_cmd_mkxip
=
XIPZ
$@
cmd_mkxip
=
$(cmd_objcopy)
&&
$(cmd_deflate_xip_data)
else
quiet_cmd_mkxip
=
$(quiet_cmd_objcopy)
cmd_mkxip
=
$(cmd_objcopy)
endif
$(obj)/xipImage
:
vmlinux FORCE
$(
call
if_changed,
objcopy
)
$(
call
if_changed,
mkxip
)
@
$(kecho)
' Physical Address of xipImage:
$(CONFIG_XIP_PHYS_ADDR)
'
$(obj)/Image $(obj)/zImage
:
FORCE
...
...
arch/arm/boot/deflate_xip_data.sh
0 → 100755
View file @
02196144
#!/bin/sh
# XIP kernel .data segment compressor
#
# 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.
# This script locates the start of the .data section in xipImage and
# substitutes it with a compressed version. The needed offsets are obtained
# from symbol addresses in vmlinux. It is expected that .data extends to
# the end of xipImage.
set
-e
VMLINUX
=
"
$1
"
XIPIMAGE
=
"
$2
"
DD
=
"dd status=none"
# Use "make V=1" to debug this script.
case
"
$KBUILD_VERBOSE
"
in
*
1
*
)
set
-x
;;
esac
sym_val
()
{
# extract hex value for symbol in $1
local
val
=
$(
$NM
"
$VMLINUX
"
|
sed
-n
"/
$1$/
{s/ .*
$/
/p;q}"
)
[
"
$val
"
]
||
{
echo
"can't find
$1
in
$VMLINUX
"
1>&2
;
exit
1
;
}
# convert from hex to decimal
echo
$((
0
x
$val
))
}
__data_loc
=
$(
sym_val __data_loc
)
_edata_loc
=
$(
sym_val _edata_loc
)
base_offset
=
$(
sym_val _xiprom
)
# convert to file based offsets
data_start
=
$((
$__data_loc
-
$base_offset
))
data_end
=
$((
$_edata_loc
-
$base_offset
))
# Make sure data occupies the last part of the file.
file_end
=
$(
stat
-c
"%s"
"
$XIPIMAGE
"
)
if
[
"
$file_end
"
!=
"
$data_end
"
]
;
then
printf
"end of xipImage doesn't match with _edata_loc (%#x vs %#x)
\n
"
\
$((
$file_end
+
$base_offset
))
$_edata_loc
2>&1
exit
1
;
fi
# be ready to clean up
trap
'rm -f "$XIPIMAGE.tmp"'
0 1 2 3
# substitute the data section by a compressed version
$DD
if
=
"
$XIPIMAGE
"
count
=
$data_start
iflag
=
count_bytes
of
=
"
$XIPIMAGE
.tmp"
$DD
if
=
"
$XIPIMAGE
"
skip
=
$data_start
iflag
=
skip_bytes |
gzip
-9
>>
"
$XIPIMAGE
.tmp"
# replace kernel binary
mv
-f
"
$XIPIMAGE
.tmp"
"
$XIPIMAGE
"
arch/arm/include/asm/cputype.h
View file @
02196144
...
...
@@ -173,6 +173,11 @@ static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
return
read_cpuid
(
CPUID_CACHETYPE
);
}
static
inline
unsigned
int
__attribute_const__
read_cpuid_mputype
(
void
)
{
return
read_cpuid
(
CPUID_MPUIR
);
}
#elif defined(CONFIG_CPU_V7M)
static
inline
unsigned
int
__attribute_const__
read_cpuid_id
(
void
)
...
...
@@ -185,6 +190,11 @@ static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
return
readl
(
BASEADDR_V7M_SCB
+
V7M_SCB_CTR
);
}
static
inline
unsigned
int
__attribute_const__
read_cpuid_mputype
(
void
)
{
return
readl
(
BASEADDR_V7M_SCB
+
MPU_TYPE
);
}
#else
/* ifdef CONFIG_CPU_CP15 / elif defined(CONFIG_CPU_V7M) */
static
inline
unsigned
int
__attribute_const__
read_cpuid_id
(
void
)
...
...
arch/arm/include/asm/elf.h
View file @
02196144
...
...
@@ -100,10 +100,15 @@ struct elf32_hdr;
extern
int
elf_check_arch
(
const
struct
elf32_hdr
*
);
#define elf_check_arch elf_check_arch
#define ELFOSABI_ARM_FDPIC 65
/* ARM FDPIC platform */
#define elf_check_fdpic(x) ((x)->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC)
#define elf_check_const_displacement(x) ((x)->e_flags & EF_ARM_PIC)
#define ELF_FDPIC_CORE_EFLAGS 0
#define vmcore_elf64_check_arch(x) (0)
extern
int
arm_elf_read_implies_exec
(
const
struct
elf32_hdr
*
,
int
);
#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(
&(ex),
stk)
extern
int
arm_elf_read_implies_exec
(
int
);
#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(stk)
struct
task_struct
;
int
dump_task_regs
(
struct
task_struct
*
t
,
elf_gregset_t
*
elfregs
);
...
...
@@ -120,6 +125,13 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
have no such handler. */
#define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0
#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \
do { \
(_r)->ARM_r7 = _exec_map_addr; \
(_r)->ARM_r8 = _interp_map_addr; \
(_r)->ARM_r9 = dynamic_addr; \
} while(0)
extern
void
elf_set_personality
(
const
struct
elf32_hdr
*
);
#define SET_PERSONALITY(ex) elf_set_personality(&(ex))
...
...
arch/arm/include/asm/mmu.h
View file @
02196144
...
...
@@ -14,6 +14,10 @@ typedef struct {
#ifdef CONFIG_VDSO
unsigned
long
vdso
;
#endif
#ifdef CONFIG_BINFMT_ELF_FDPIC
unsigned
long
exec_fdpic_loadmap
;
unsigned
long
interp_fdpic_loadmap
;
#endif
}
mm_context_t
;
#ifdef CONFIG_CPU_HAS_ASID
...
...
@@ -33,6 +37,10 @@ typedef struct {
*/
typedef
struct
{
unsigned
long
end_brk
;
#ifdef CONFIG_BINFMT_ELF_FDPIC
unsigned
long
exec_fdpic_loadmap
;
unsigned
long
interp_fdpic_loadmap
;
#endif
}
mm_context_t
;
#endif
...
...
arch/arm/include/asm/mpu.h
View file @
02196144
#ifndef __ARM_MPU_H
#define __ARM_MPU_H
#ifdef CONFIG_ARM_MPU
/* MPUIR layout */
#define MPUIR_nU 1
#define MPUIR_DREGION 8
...
...
@@ -17,6 +15,11 @@
/* MPU D/I Size Register fields */
#define MPU_RSR_SZ 1
#define MPU_RSR_EN 0
#define MPU_RSR_SD 8
/* Number of subregions (SD) */
#define MPU_NR_SUBREGS 8
#define MPU_MIN_SUBREG_SIZE 256
/* The D/I RSR value for an enabled region spanning the whole of memory */
#define MPU_RSR_ALL_MEM 63
...
...
@@ -38,6 +41,7 @@
#endif
/* Access permission bits of ACR (only define those that we use)*/
#define MPU_AP_PL1RO_PL0NA (0x5 << 8)
#define MPU_AP_PL1RW_PL0RW (0x3 << 8)
#define MPU_AP_PL1RW_PL0R0 (0x2 << 8)
#define MPU_AP_PL1RW_PL0NA (0x1 << 8)
...
...
@@ -46,7 +50,7 @@
#define MPU_PROBE_REGION 0
#define MPU_BG_REGION 1
#define MPU_RAM_REGION 2
#define MPU_
VECTORS_REGION
3
#define MPU_
ROM_REGION
3
/* Maximum number of regions Linux is interested in */
#define MPU_MAX_REGIONS 16
...
...
@@ -64,13 +68,23 @@ struct mpu_rgn {
};
struct
mpu_rgn_info
{
u
32
mpuir
;
u
nsigned
int
used
;
struct
mpu_rgn
rgns
[
MPU_MAX_REGIONS
];
};
extern
struct
mpu_rgn_info
mpu_rgn_info
;
#endif
/* __ASSEMBLY__ */
#ifdef CONFIG_ARM_MPU
extern
void
__init
adjust_lowmem_bounds_mpu
(
void
);
extern
void
__init
mpu_setup
(
void
);
#endif
/* CONFIG_ARM_MPU */
#else
static
inline
void
adjust_lowmem_bounds_mpu
(
void
)
{}
static
inline
void
mpu_setup
(
void
)
{}
#endif
/* !CONFIG_ARM_MPU */
#endif
/* __ASSEMBLY__ */
#endif
arch/arm/include/asm/processor.h
View file @
02196144
...
...
@@ -47,15 +47,24 @@ struct thread_struct {
#define INIT_THREAD { }
#ifdef CONFIG_MMU
#define nommu_start_thread(regs) do { } while (0)
#else
#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
#endif
#define start_thread(regs,pc,sp) \
({ \
unsigned long r7, r8, r9; \
\
if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC)) { \
r7 = regs->ARM_r7; \
r8 = regs->ARM_r8; \
r9 = regs->ARM_r9; \
} \
memset(regs->uregs, 0, sizeof(regs->uregs)); \
if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) && \
current->personality & FDPIC_FUNCPTRS) { \
regs->ARM_r7 = r7; \
regs->ARM_r8 = r8; \
regs->ARM_r9 = r9; \
regs->ARM_r10 = current->mm->start_data; \
} else if (!IS_ENABLED(CONFIG_MMU)) \
regs->ARM_r10 = current->mm->start_data; \
if (current->personality & ADDR_LIMIT_32BIT) \
regs->ARM_cpsr = USR_MODE; \
else \
...
...
@@ -65,7 +74,6 @@ struct thread_struct {
regs->ARM_cpsr |= PSR_ENDSTATE; \
regs->ARM_pc = pc & ~1;
/* pc */
\
regs->ARM_sp = sp;
/* sp */
\
nommu_start_thread(regs); \
})
/* Forward declaration, a strange C thing */
...
...
arch/arm/include/asm/smp.h
View file @
02196144
...
...
@@ -60,7 +60,7 @@ asmlinkage void secondary_start_kernel(void);
*/
struct
secondary_data
{
union
{
unsigned
long
mpu_rgn_szr
;
struct
mpu_rgn_info
*
mpu_rgn_info
;
u64
pgdir
;
};
unsigned
long
swapper_pg_dir
;
...
...
arch/arm/include/asm/ucontext.h
View file @
02196144
...
...
@@ -2,6 +2,7 @@
#define _ASMARM_UCONTEXT_H
#include <asm/fpstate.h>
#include <asm/user.h>
/*
* struct sigcontext only has room for the basic registers, but struct
...
...
arch/arm/include/asm/v7m.h
View file @
02196144
...
...
@@ -57,6 +57,16 @@
#define V7M_SCB_CCSIDR 0x80
/* Cache size ID register */
#define V7M_SCB_CSSELR 0x84
/* Cache size selection register */
/* Memory-mapped MPU registers for M-class */
#define MPU_TYPE 0x90
#define MPU_CTRL 0x94
#define MPU_CTRL_ENABLE 1
#define MPU_CTRL_PRIVDEFENA (1 << 2)
#define MPU_RNR 0x98
#define MPU_RBAR 0x9c
#define MPU_RASR 0xa0
/* Cache opeartions */
#define V7M_SCB_ICIALLU 0x250
/* I-cache invalidate all to PoU */
#define V7M_SCB_ICIMVAU 0x258
/* I-cache invalidate by MVA to PoU */
...
...
arch/arm/include/uapi/asm/ptrace.h
View file @
02196144
...
...
@@ -31,6 +31,10 @@
#define PTRACE_SETVFPREGS 28
#define PTRACE_GETHBPREGS 29
#define PTRACE_SETHBPREGS 30
#define PTRACE_GETFDPIC 31
#define PTRACE_GETFDPIC_EXEC 0
#define PTRACE_GETFDPIC_INTERP 1
/*
* PSR bits
...
...
arch/arm/include/uapi/asm/unistd.h
View file @
02196144
...
...
@@ -35,5 +35,6 @@
#define __ARM_NR_usr26 (__ARM_NR_BASE+3)
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
#define __ARM_NR_get_tls (__ARM_NR_BASE+6)
#endif
/* _UAPI__ASM_ARM_UNISTD_H */
arch/arm/kernel/Makefile
View file @
02196144
...
...
@@ -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)
...
...
arch/arm/kernel/asm-offsets.c
View file @
02196144
...
...
@@ -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
;
}
arch/arm/kernel/elf.c
View file @
02196144
...
...
@@ -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
arch/arm/kernel/head-common.S
View file @
02196144
...
...
@@ -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
1
b
mov
fp
,
#
0
@
Clear
BSS
(
and
zero
fp
)
1
:
cmp
r6
,
r7
strcc
fp
,
[
r6
],#
4
bcc
1
b
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
mov
r7
,
r1
mov
r8
,
r2
mov
r10
,
r0
adr
r4
,
__mmap_switched_data
mov
fp
,
#
0
#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_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
@
r
7
.
long
cr_alignment
@
r
3
#else
.
long
0
@
r
7
.
long
0
@
r
3
#endif
.
long
init_thread_union
+
THREAD_START_SP
@
sp
.
size
__mmap_switched_data
,
.
-
__mmap_switched_data
/*
...
...
arch/arm/kernel/head-inflate-data.c
0 → 100644
View file @
02196144
/*
* 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
;
}
arch/arm/kernel/head-nommu.S
View file @
02196144
...
...
@@ -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
__se
tup_mpu
@
Initialize
the
MPU
ldr
r6
,
[
r7
]
@
get
secondary_data
.
mpu_
rgn_info
bl
__se
condary_setup_mpu
@
Initialize
the
MPU
#endif
badr
lr
,
1
f
@
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,56 +216,126 @@ 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
b
ne
__error_p
@
Fail
:
ARM_MPU
on
NOT
v7
PMSA
b
xne
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
b
eq
__error_p
@
Fail
:
ARM_MPU
and
no
MPU
b
xeq
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
setup_region
r0
,
r5
,
r6
,
MPU_DATA_SIDE
,
r12
@
PHYS_OFFSET
,
shared
,
enabled
beq
1
f
@
Memory
-
map
not
unified
setup_region
r0
,
r5
,
r6
,
MPU_INSTR_SIDE
@
PHYS_OFFSET
,
shared
,
enabled
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
@
4
GB
region
,
enabled
setup_region
r0
,
r5
,
r6
,
MPU_DATA_SIDE
@
0x0
,
BG
region
,
enabled
setup_region
r0
,
r5
,
r6
,
MPU_DATA_SIDE
,
r12
@
0x0
,
BG
region
,
enabled
beq
2
f
@
Memory
-
map
not
unified
setup_region
r0
,
r5
,
r6
,
MPU_INSTR_SIDE
@
0x0
,
BG
region
,
enabled
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
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
3
f
@
Memory
-
map
not
unified
setup_region
r0
,
r5
,
r6
,
MPU_INSTR_SIDE
@
VECTORS_BASE
,
PL0
NA
,
enabled
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
2
f
setup_region
r0
,
r5
,
r6
,
MPU_INSTR_SIDE
2
:
isb
mrc
p15
,
0
,
r0
,
c0
,
c0
,
4
@
Reevaluate
the
MPUIR
cmp
r4
,
#
0
bgt
1
b
/
*
Enable
the
MPU
*/
mrc
p15
,
0
,
r0
,
c1
,
c0
,
0
@
Read
SCTLR
...
...
@@ -258,7 +343,10 @@ ENTRY(__setup_mpu)
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"
arch/arm/kernel/signal.c
View file @
02196144
...
...
@@ -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
;
...
...
arch/arm/kernel/signal.h
0 → 100644
View file @
02196144
#include <asm/ucontext.h>
struct
sigframe
{
struct
ucontext
uc
;
unsigned
long
retcode
[
4
];
};
struct
rt_sigframe
{
struct
siginfo
info
;
struct
sigframe
sig
;
};
arch/arm/kernel/sigreturn_codes.S
View file @
02196144
...
...
@@ -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
*
al
gorithm
uses
two
words
copy
regardless
whether
*
it
is
thumb
case
or
not
,
so
we
need
additional
*
word
after
real
last
entry
.
*
Note
on
add
i
tional
space
:
setup_return
in
signal
.
c
*
al
ways
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
arch/arm/kernel/smp.c
View file @
02196144
...
...
@@ -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
...
...
arch/arm/kernel/traps.c
View file @
02196144
...
...
@@ -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
...
...
arch/arm/kernel/vmlinux-xip.lds.S
View file @
02196144
...
...
@@ -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_
SMP
PERCPU_SECTION
(
L1_CACHE_BYTES
)
#ifdef CONFIG_
ARM_MPU
.
=
ALIGN
(
SZ_128K
)
;
#endif
_exiprom
=
.
; /* End of XIP ROM area */
__data_loc
=
ALIGN
(
4
)
; /* location in binary */
.
=
PAGE_OFFSET
+
TEXT_OFFSET
;
.
data
:
AT
(
__data_loc
)
{
_data
=
.
; /* address in memory */
_sdata
=
.
;
/
*
*
first
,
the
init
task
union
,
aligned
*
to
an
8192
byte
boundary
.
/*
*
From
this
point
,
stuff
is
considered
writable
and
will
be
copied
to
RAM
*/
INIT_TASK_DATA
(
THREAD_SIZE
)
__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
)
.
=
ALIGN
(
PAGE_SIZE
)
;
__init_end
=
.
;
*(.
data..
ro_after_init
)
NOSAVE_DATA
CACHELINE_ALIGNED_DATA
(
L1_CACHE_BYTES
)
READ_MOSTLY_DATA
(
L1_CACHE_BYTES
)
}
#ifdef CONFIG_SMP
PERCPU_SECTION
(
L1_CACHE_BYTES
)
#endif
/
*
*
and
the
usual
data
section
*
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_DATA
CONSTRUCTORS
_edata
=
.
;
}
_edata_loc
=
__data_loc
+
SIZEOF
(
.
data
)
;
.
data.endmark
:
AT
(
ADDR
(
.
data
.
endmark
)
-
LOAD_OFFSET
)
{
}
_edata_loc
=
LOADADDR
(
.
data
.
endmark
)
;
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
1
M
should
suit
most
users
.
*
_exiprom
is
aligned
as
1
/
8
of
1
M
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
arch/arm/kernel/vmlinux.lds.S
View file @
02196144
...
...
@@ -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
RW_DATA_SECTION
(
L1_CACHE_BYTES
,
PAGE_SIZE
,
THREAD_SIZE
)
_edata
=
.
;
}
_edata_loc
=
__data_loc
+
SIZEOF
(
.
data
)
;
BUG_TABLE
#ifdef CONFIG_HAVE_TCM
/
*
...
...
arch/arm/mm/Makefile
View file @
02196144
...
...
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \
ifneq
($(CONFIG_MMU),y)
obj-y
+=
nommu.o
obj-$(CONFIG_ARM_MPU)
+=
pmsa-v7.o
endif
obj-$(CONFIG_ARM_PTDUMP)
+=
dump.o
...
...
arch/arm/mm/nommu.c
View file @
02196144
...
...
@@ -27,259 +27,7 @@ unsigned long vectors_base;
#ifdef CONFIG_ARM_MPU
struct
mpu_rgn_info
mpu_rgn_info
;
/* Region number */
static
void
rgnr_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c2, 0"
:
:
"r"
(
v
));
}
/* Data-side / unified region attributes */
/* Region access control register */
static
void
dracr_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c1, 4"
:
:
"r"
(
v
));
}
/* Region size register */
static
void
drsr_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c1, 2"
:
:
"r"
(
v
));
}
/* Region base address register */
static
void
drbar_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c1, 0"
:
:
"r"
(
v
));
}
static
u32
drbar_read
(
void
)
{
u32
v
;
asm
(
"mrc p15, 0, %0, c6, c1, 0"
:
"=r"
(
v
));
return
v
;
}
/* Optional instruction-side region attributes */
/* I-side Region access control register */
static
void
iracr_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c1, 5"
:
:
"r"
(
v
));
}
/* I-side Region size register */
static
void
irsr_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c1, 3"
:
:
"r"
(
v
));
}
/* I-side Region base address register */
static
void
irbar_write
(
u32
v
)
{
asm
(
"mcr p15, 0, %0, c6, c1, 1"
:
:
"r"
(
v
));
}
static
unsigned
long
irbar_read
(
void
)
{
unsigned
long
v
;
asm
(
"mrc p15, 0, %0, c6, c1, 1"
:
"=r"
(
v
));
return
v
;
}
/* MPU initialisation functions */
void
__init
adjust_lowmem_bounds_mpu
(
void
)
{
phys_addr_t
phys_offset
=
PHYS_OFFSET
;
phys_addr_t
aligned_region_size
,
specified_mem_size
,
rounded_mem_size
;
struct
memblock_region
*
reg
;
bool
first
=
true
;
phys_addr_t
mem_start
;
phys_addr_t
mem_end
;
for_each_memblock
(
memory
,
reg
)
{
if
(
first
)
{
/*
* Initially only use memory continuous from
* PHYS_OFFSET */
if
(
reg
->
base
!=
phys_offset
)
panic
(
"First memory bank must be contiguous from PHYS_OFFSET"
);
mem_start
=
reg
->
base
;
mem_end
=
reg
->
base
+
reg
->
size
;
specified_mem_size
=
reg
->
size
;
first
=
false
;
}
else
{
/*
* memblock auto merges contiguous blocks, remove
* all blocks afterwards in one go (we can't remove
* blocks separately while iterating)
*/
pr_notice
(
"Ignoring RAM after %pa, memory at %pa ignored
\n
"
,
&
mem_end
,
&
reg
->
base
);
memblock_remove
(
reg
->
base
,
0
-
reg
->
base
);
break
;
}
}
/*
* MPU has curious alignment requirements: Size must be power of 2, and
* region start must be aligned to the region size
*/
if
(
phys_offset
!=
0
)
pr_info
(
"PHYS_OFFSET != 0 => MPU Region size constrained by alignment requirements
\n
"
);
/*
* Maximum aligned region might overflow phys_addr_t if phys_offset is
* 0. Hence we keep everything below 4G until we take the smaller of
* the aligned_region_size and rounded_mem_size, one of which is
* guaranteed to be smaller than the maximum physical address.
*/
aligned_region_size
=
(
phys_offset
-
1
)
^
(
phys_offset
);
/* Find the max power-of-two sized region that fits inside our bank */
rounded_mem_size
=
(
1
<<
__fls
(
specified_mem_size
))
-
1
;
/* The actual region size is the smaller of the two */
aligned_region_size
=
aligned_region_size
<
rounded_mem_size
?
aligned_region_size
+
1
:
rounded_mem_size
+
1
;
if
(
aligned_region_size
!=
specified_mem_size
)
{
pr_warn
(
"Truncating memory from %pa to %pa (MPU region constraints)"
,
&
specified_mem_size
,
&
aligned_region_size
);
memblock_remove
(
mem_start
+
aligned_region_size
,
specified_mem_size
-
aligned_region_size
);
mem_end
=
mem_start
+
aligned_region_size
;
}
pr_debug
(
"MPU Region from %pa size %pa (end %pa))
\n
"
,
&
phys_offset
,
&
aligned_region_size
,
&
mem_end
);
}
static
int
mpu_present
(
void
)
{
return
((
read_cpuid_ext
(
CPUID_EXT_MMFR0
)
&
MMFR0_PMSA
)
==
MMFR0_PMSAv7
);
}
static
int
mpu_max_regions
(
void
)
{
/*
* We don't support a different number of I/D side regions so if we
* have separate instruction and data memory maps then return
* whichever side has a smaller number of supported regions.
*/
u32
dregions
,
iregions
,
mpuir
;
mpuir
=
read_cpuid
(
CPUID_MPUIR
);
dregions
=
iregions
=
(
mpuir
&
MPUIR_DREGION_SZMASK
)
>>
MPUIR_DREGION
;
/* Check for separate d-side and i-side memory maps */
if
(
mpuir
&
MPUIR_nU
)
iregions
=
(
mpuir
&
MPUIR_IREGION_SZMASK
)
>>
MPUIR_IREGION
;
/* Use the smallest of the two maxima */
return
min
(
dregions
,
iregions
);
}
static
int
mpu_iside_independent
(
void
)
{
/* MPUIR.nU specifies whether there is *not* a unified memory map */
return
read_cpuid
(
CPUID_MPUIR
)
&
MPUIR_nU
;
}
static
int
mpu_min_region_order
(
void
)
{
u32
drbar_result
,
irbar_result
;
/* We've kept a region free for this probing */
rgnr_write
(
MPU_PROBE_REGION
);
isb
();
/*
* As per ARM ARM, write 0xFFFFFFFC to DRBAR to find the minimum
* region order
*/
drbar_write
(
0xFFFFFFFC
);
drbar_result
=
irbar_result
=
drbar_read
();
drbar_write
(
0x0
);
/* If the MPU is non-unified, we use the larger of the two minima*/
if
(
mpu_iside_independent
())
{
irbar_write
(
0xFFFFFFFC
);
irbar_result
=
irbar_read
();
irbar_write
(
0x0
);
}
isb
();
/* Ensure that MPU region operations have completed */
/* Return whichever result is larger */
return
__ffs
(
max
(
drbar_result
,
irbar_result
));
}
static
int
mpu_setup_region
(
unsigned
int
number
,
phys_addr_t
start
,
unsigned
int
size_order
,
unsigned
int
properties
)
{
u32
size_data
;
/* We kept a region free for probing resolution of MPU regions*/
if
(
number
>
mpu_max_regions
()
||
number
==
MPU_PROBE_REGION
)
return
-
ENOENT
;
if
(
size_order
>
32
)
return
-
ENOMEM
;
if
(
size_order
<
mpu_min_region_order
())
return
-
ENOMEM
;
/* Writing N to bits 5:1 (RSR_SZ) specifies region size 2^N+1 */
size_data
=
((
size_order
-
1
)
<<
MPU_RSR_SZ
)
|
1
<<
MPU_RSR_EN
;
dsb
();
/* Ensure all previous data accesses occur with old mappings */
rgnr_write
(
number
);
isb
();
drbar_write
(
start
);
dracr_write
(
properties
);
isb
();
/* Propagate properties before enabling region */
drsr_write
(
size_data
);
/* Check for independent I-side registers */
if
(
mpu_iside_independent
())
{
irbar_write
(
start
);
iracr_write
(
properties
);
isb
();
irsr_write
(
size_data
);
}
isb
();
/* Store region info (we treat i/d side the same, so only store d) */
mpu_rgn_info
.
rgns
[
number
].
dracr
=
properties
;
mpu_rgn_info
.
rgns
[
number
].
drbar
=
start
;
mpu_rgn_info
.
rgns
[
number
].
drsr
=
size_data
;
return
0
;
}
/*
* Set up default MPU regions, doing nothing if there is no MPU
*/
void
__init
mpu_setup
(
void
)
{
int
region_err
;
if
(
!
mpu_present
())
return
;
region_err
=
mpu_setup_region
(
MPU_RAM_REGION
,
PHYS_OFFSET
,
ilog2
(
memblock
.
memory
.
regions
[
0
].
size
),
MPU_AP_PL1RW_PL0RW
|
MPU_RGN_NORMAL
);
if
(
region_err
)
{
panic
(
"MPU region initialization failure! %d"
,
region_err
);
}
else
{
pr_info
(
"Using ARMv7 PMSA Compliant MPU. "
"Region independence: %s, Max regions: %d
\n
"
,
mpu_iside_independent
()
?
"Yes"
:
"No"
,
mpu_max_regions
());
}
}
#else
static
void
adjust_lowmem_bounds_mpu
(
void
)
{}
static
void
__init
mpu_setup
(
void
)
{}
#endif
/* CONFIG_ARM_MPU */
#endif
#ifdef CONFIG_CPU_CP15
#ifdef CONFIG_CPU_HIGH_VECTOR
...
...
arch/arm/mm/pmsa-v7.c
0 → 100644
View file @
02196144
/*
* Based on linux/arch/arm/mm/nommu.c
*
* ARM PMSAv7 supporting functions.
*/
#include <linux/bitops.h>
#include <linux/memblock.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/cputype.h>
#include <asm/mpu.h>
#include <asm/sections.h>
#include "mm.h"
struct
region
{
phys_addr_t
base
;
phys_addr_t
size
;
unsigned
long
subreg
;
};
static
struct
region
__initdata
mem
[
MPU_MAX_REGIONS
];
#ifdef CONFIG_XIP_KERNEL
static
struct
region
__initdata
xip
[
MPU_MAX_REGIONS
];
#endif
static
unsigned
int
__initdata
mpu_min_region_order
;
static
unsigned
int
__initdata
mpu_max_regions
;
static
int
__init
__mpu_min_region_order
(
void
);
static
int
__init
__mpu_max_regions
(
void
);
#ifndef CONFIG_CPU_V7M
#define DRBAR __ACCESS_CP15(c6, 0, c1, 0)
#define IRBAR __ACCESS_CP15(c6, 0, c1, 1)
#define DRSR __ACCESS_CP15(c6, 0, c1, 2)
#define IRSR __ACCESS_CP15(c6, 0, c1, 3)
#define DRACR __ACCESS_CP15(c6, 0, c1, 4)
#define IRACR __ACCESS_CP15(c6, 0, c1, 5)
#define RNGNR __ACCESS_CP15(c6, 0, c2, 0)
/* Region number */
static
inline
void
rgnr_write
(
u32
v
)
{
write_sysreg
(
v
,
RNGNR
);
}
/* Data-side / unified region attributes */
/* Region access control register */
static
inline
void
dracr_write
(
u32
v
)
{
write_sysreg
(
v
,
DRACR
);
}
/* Region size register */
static
inline
void
drsr_write
(
u32
v
)
{
write_sysreg
(
v
,
DRSR
);
}
/* Region base address register */
static
inline
void
drbar_write
(
u32
v
)
{
write_sysreg
(
v
,
DRBAR
);
}
static
inline
u32
drbar_read
(
void
)
{
return
read_sysreg
(
DRBAR
);
}
/* Optional instruction-side region attributes */
/* I-side Region access control register */
static
inline
void
iracr_write
(
u32
v
)
{
write_sysreg
(
v
,
IRACR
);
}
/* I-side Region size register */
static
inline
void
irsr_write
(
u32
v
)
{
write_sysreg
(
v
,
IRSR
);
}
/* I-side Region base address register */
static
inline
void
irbar_write
(
u32
v
)
{
write_sysreg
(
v
,
IRBAR
);
}
static
inline
u32
irbar_read
(
void
)
{
return
read_sysreg
(
IRBAR
);
}
#else
static
inline
void
rgnr_write
(
u32
v
)
{
writel_relaxed
(
v
,
BASEADDR_V7M_SCB
+
MPU_RNR
);
}
/* Data-side / unified region attributes */
/* Region access control register */
static
inline
void
dracr_write
(
u32
v
)
{
u32
rsr
=
readl_relaxed
(
BASEADDR_V7M_SCB
+
MPU_RASR
)
&
GENMASK
(
15
,
0
);
writel_relaxed
((
v
<<
16
)
|
rsr
,
BASEADDR_V7M_SCB
+
MPU_RASR
);
}
/* Region size register */
static
inline
void
drsr_write
(
u32
v
)
{
u32
racr
=
readl_relaxed
(
BASEADDR_V7M_SCB
+
MPU_RASR
)
&
GENMASK
(
31
,
16
);
writel_relaxed
(
v
|
racr
,
BASEADDR_V7M_SCB
+
MPU_RASR
);
}
/* Region base address register */
static
inline
void
drbar_write
(
u32
v
)
{
writel_relaxed
(
v
,
BASEADDR_V7M_SCB
+
MPU_RBAR
);
}
static
inline
u32
drbar_read
(
void
)
{
return
readl_relaxed
(
BASEADDR_V7M_SCB
+
MPU_RBAR
);
}
/* ARMv7-M only supports a unified MPU, so I-side operations are nop */
static
inline
void
iracr_write
(
u32
v
)
{}
static
inline
void
irsr_write
(
u32
v
)
{}
static
inline
void
irbar_write
(
u32
v
)
{}
static
inline
unsigned
long
irbar_read
(
void
)
{
return
0
;}
#endif
static
int
__init
mpu_present
(
void
)
{
return
((
read_cpuid_ext
(
CPUID_EXT_MMFR0
)
&
MMFR0_PMSA
)
==
MMFR0_PMSAv7
);
}
static
bool
__init
try_split_region
(
phys_addr_t
base
,
phys_addr_t
size
,
struct
region
*
region
)
{
unsigned
long
subreg
,
bslots
,
sslots
;
phys_addr_t
abase
=
base
&
~
(
size
-
1
);
phys_addr_t
asize
=
base
+
size
-
abase
;
phys_addr_t
p2size
=
1
<<
__fls
(
asize
);
phys_addr_t
bdiff
,
sdiff
;
if
(
p2size
!=
asize
)
p2size
*=
2
;
bdiff
=
base
-
abase
;
sdiff
=
p2size
-
asize
;
subreg
=
p2size
/
MPU_NR_SUBREGS
;
if
((
bdiff
%
subreg
)
||
(
sdiff
%
subreg
))
return
false
;
bslots
=
bdiff
/
subreg
;
sslots
=
sdiff
/
subreg
;
if
(
bslots
||
sslots
)
{
int
i
;
if
(
subreg
<
MPU_MIN_SUBREG_SIZE
)
return
false
;
if
(
bslots
+
sslots
>
MPU_NR_SUBREGS
)
return
false
;
for
(
i
=
0
;
i
<
bslots
;
i
++
)
_set_bit
(
i
,
&
region
->
subreg
);
for
(
i
=
1
;
i
<=
sslots
;
i
++
)
_set_bit
(
MPU_NR_SUBREGS
-
i
,
&
region
->
subreg
);
}
region
->
base
=
abase
;
region
->
size
=
p2size
;
return
true
;
}
static
int
__init
allocate_region
(
phys_addr_t
base
,
phys_addr_t
size
,
unsigned
int
limit
,
struct
region
*
regions
)
{
int
count
=
0
;
phys_addr_t
diff
=
size
;
int
attempts
=
MPU_MAX_REGIONS
;
while
(
diff
)
{
/* Try cover region as is (maybe with help of subregions) */
if
(
try_split_region
(
base
,
size
,
&
regions
[
count
]))
{
count
++
;
base
+=
size
;
diff
-=
size
;
size
=
diff
;
}
else
{
/*
* Maximum aligned region might overflow phys_addr_t
* if "base" is 0. Hence we keep everything below 4G
* until we take the smaller of the aligned region
* size ("asize") and rounded region size ("p2size"),
* one of which is guaranteed to be smaller than the
* maximum physical address.
*/
phys_addr_t
asize
=
(
base
-
1
)
^
base
;
phys_addr_t
p2size
=
(
1
<<
__fls
(
diff
))
-
1
;
size
=
asize
<
p2size
?
asize
+
1
:
p2size
+
1
;
}
if
(
count
>
limit
)
break
;
if
(
!
attempts
)
break
;
attempts
--
;
}
return
count
;
}
/* MPU initialisation functions */
void
__init
adjust_lowmem_bounds_mpu
(
void
)
{
phys_addr_t
specified_mem_size
=
0
,
total_mem_size
=
0
;
struct
memblock_region
*
reg
;
bool
first
=
true
;
phys_addr_t
mem_start
;
phys_addr_t
mem_end
;
unsigned
int
mem_max_regions
;
int
num
,
i
;
if
(
!
mpu_present
())
return
;
/* Free-up MPU_PROBE_REGION */
mpu_min_region_order
=
__mpu_min_region_order
();
/* How many regions are supported */
mpu_max_regions
=
__mpu_max_regions
();
mem_max_regions
=
min
((
unsigned
int
)
MPU_MAX_REGIONS
,
mpu_max_regions
);
/* We need to keep one slot for background region */
mem_max_regions
--
;
#ifndef CONFIG_CPU_V7M
/* ... and one for vectors */
mem_max_regions
--
;
#endif
#ifdef CONFIG_XIP_KERNEL
/* plus some regions to cover XIP ROM */
num
=
allocate_region
(
CONFIG_XIP_PHYS_ADDR
,
__pa
(
_exiprom
)
-
CONFIG_XIP_PHYS_ADDR
,
mem_max_regions
,
xip
);
mem_max_regions
-=
num
;
#endif
for_each_memblock
(
memory
,
reg
)
{
if
(
first
)
{
phys_addr_t
phys_offset
=
PHYS_OFFSET
;
/*
* Initially only use memory continuous from
* PHYS_OFFSET */
if
(
reg
->
base
!=
phys_offset
)
panic
(
"First memory bank must be contiguous from PHYS_OFFSET"
);
mem_start
=
reg
->
base
;
mem_end
=
reg
->
base
+
reg
->
size
;
specified_mem_size
=
reg
->
size
;
first
=
false
;
}
else
{
/*
* memblock auto merges contiguous blocks, remove
* all blocks afterwards in one go (we can't remove
* blocks separately while iterating)
*/
pr_notice
(
"Ignoring RAM after %pa, memory at %pa ignored
\n
"
,
&
mem_end
,
&
reg
->
base
);
memblock_remove
(
reg
->
base
,
0
-
reg
->
base
);
break
;
}
}
num
=
allocate_region
(
mem_start
,
specified_mem_size
,
mem_max_regions
,
mem
);
for
(
i
=
0
;
i
<
num
;
i
++
)
{
unsigned
long
subreg
=
mem
[
i
].
size
/
MPU_NR_SUBREGS
;
total_mem_size
+=
mem
[
i
].
size
-
subreg
*
hweight_long
(
mem
[
i
].
subreg
);
pr_debug
(
"MPU: base %pa size %pa disable subregions: %*pbl
\n
"
,
&
mem
[
i
].
base
,
&
mem
[
i
].
size
,
MPU_NR_SUBREGS
,
&
mem
[
i
].
subreg
);
}
if
(
total_mem_size
!=
specified_mem_size
)
{
pr_warn
(
"Truncating memory from %pa to %pa (MPU region constraints)"
,
&
specified_mem_size
,
&
total_mem_size
);
memblock_remove
(
mem_start
+
total_mem_size
,
specified_mem_size
-
total_mem_size
);
}
}
static
int
__init
__mpu_max_regions
(
void
)
{
/*
* We don't support a different number of I/D side regions so if we
* have separate instruction and data memory maps then return
* whichever side has a smaller number of supported regions.
*/
u32
dregions
,
iregions
,
mpuir
;
mpuir
=
read_cpuid_mputype
();
dregions
=
iregions
=
(
mpuir
&
MPUIR_DREGION_SZMASK
)
>>
MPUIR_DREGION
;
/* Check for separate d-side and i-side memory maps */
if
(
mpuir
&
MPUIR_nU
)
iregions
=
(
mpuir
&
MPUIR_IREGION_SZMASK
)
>>
MPUIR_IREGION
;
/* Use the smallest of the two maxima */
return
min
(
dregions
,
iregions
);
}
static
int
__init
mpu_iside_independent
(
void
)
{
/* MPUIR.nU specifies whether there is *not* a unified memory map */
return
read_cpuid_mputype
()
&
MPUIR_nU
;
}
static
int
__init
__mpu_min_region_order
(
void
)
{
u32
drbar_result
,
irbar_result
;
/* We've kept a region free for this probing */
rgnr_write
(
MPU_PROBE_REGION
);
isb
();
/*
* As per ARM ARM, write 0xFFFFFFFC to DRBAR to find the minimum
* region order
*/
drbar_write
(
0xFFFFFFFC
);
drbar_result
=
irbar_result
=
drbar_read
();
drbar_write
(
0x0
);
/* If the MPU is non-unified, we use the larger of the two minima*/
if
(
mpu_iside_independent
())
{
irbar_write
(
0xFFFFFFFC
);
irbar_result
=
irbar_read
();
irbar_write
(
0x0
);
}
isb
();
/* Ensure that MPU region operations have completed */
/* Return whichever result is larger */
return
__ffs
(
max
(
drbar_result
,
irbar_result
));
}
static
int
__init
mpu_setup_region
(
unsigned
int
number
,
phys_addr_t
start
,
unsigned
int
size_order
,
unsigned
int
properties
,
unsigned
int
subregions
,
bool
need_flush
)
{
u32
size_data
;
/* We kept a region free for probing resolution of MPU regions*/
if
(
number
>
mpu_max_regions
||
number
>=
MPU_MAX_REGIONS
)
return
-
ENOENT
;
if
(
size_order
>
32
)
return
-
ENOMEM
;
if
(
size_order
<
mpu_min_region_order
)
return
-
ENOMEM
;
/* Writing N to bits 5:1 (RSR_SZ) specifies region size 2^N+1 */
size_data
=
((
size_order
-
1
)
<<
MPU_RSR_SZ
)
|
1
<<
MPU_RSR_EN
;
size_data
|=
subregions
<<
MPU_RSR_SD
;
if
(
need_flush
)
flush_cache_all
();
dsb
();
/* Ensure all previous data accesses occur with old mappings */
rgnr_write
(
number
);
isb
();
drbar_write
(
start
);
dracr_write
(
properties
);
isb
();
/* Propagate properties before enabling region */
drsr_write
(
size_data
);
/* Check for independent I-side registers */
if
(
mpu_iside_independent
())
{
irbar_write
(
start
);
iracr_write
(
properties
);
isb
();
irsr_write
(
size_data
);
}
isb
();
/* Store region info (we treat i/d side the same, so only store d) */
mpu_rgn_info
.
rgns
[
number
].
dracr
=
properties
;
mpu_rgn_info
.
rgns
[
number
].
drbar
=
start
;
mpu_rgn_info
.
rgns
[
number
].
drsr
=
size_data
;
mpu_rgn_info
.
used
++
;
return
0
;
}
/*
* Set up default MPU regions, doing nothing if there is no MPU
*/
void
__init
mpu_setup
(
void
)
{
int
i
,
region
=
0
,
err
=
0
;
if
(
!
mpu_present
())
return
;
/* Setup MPU (order is important) */
/* Background */
err
|=
mpu_setup_region
(
region
++
,
0
,
32
,
MPU_ACR_XN
|
MPU_RGN_STRONGLY_ORDERED
|
MPU_AP_PL1RW_PL0NA
,
0
,
false
);
#ifdef CONFIG_XIP_KERNEL
/* ROM */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xip
);
i
++
)
{
/*
* In case we overwrite RAM region we set earlier in
* head-nommu.S (which is cachable) all subsequent
* data access till we setup RAM bellow would be done
* with BG region (which is uncachable), thus we need
* to clean and invalidate cache.
*/
bool
need_flush
=
region
==
MPU_RAM_REGION
;
if
(
!
xip
[
i
].
size
)
continue
;
err
|=
mpu_setup_region
(
region
++
,
xip
[
i
].
base
,
ilog2
(
xip
[
i
].
size
),
MPU_AP_PL1RO_PL0NA
|
MPU_RGN_NORMAL
,
xip
[
i
].
subreg
,
need_flush
);
}
#endif
/* RAM */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
mem
);
i
++
)
{
if
(
!
mem
[
i
].
size
)
continue
;
err
|=
mpu_setup_region
(
region
++
,
mem
[
i
].
base
,
ilog2
(
mem
[
i
].
size
),
MPU_AP_PL1RW_PL0RW
|
MPU_RGN_NORMAL
,
mem
[
i
].
subreg
,
false
);
}
/* Vectors */
#ifndef CONFIG_CPU_V7M
err
|=
mpu_setup_region
(
region
++
,
vectors_base
,
ilog2
(
2
*
PAGE_SIZE
),
MPU_AP_PL1RW_PL0NA
|
MPU_RGN_NORMAL
,
0
,
false
);
#endif
if
(
err
)
{
panic
(
"MPU region initialization failure! %d"
,
err
);
}
else
{
pr_info
(
"Using ARMv7 PMSA Compliant MPU. "
"Region independence: %s, Used %d of %d regions
\n
"
,
mpu_iside_independent
()
?
"Yes"
:
"No"
,
mpu_rgn_info
.
used
,
mpu_max_regions
);
}
}
fs/Kconfig.binfmt
View file @
02196144
...
...
@@ -34,8 +34,8 @@ config ARCH_BINFMT_ELF_STATE
config BINFMT_ELF_FDPIC
bool "Kernel support for FDPIC ELF binaries"
default y
depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
default y
if !BINFMT_ELF
depends on (
ARM ||
FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
select ELFCORE
help
ELF FDPIC binaries are based on ELF, but allow the individual load
...
...
fs/binfmt_elf.c
View file @
02196144
...
...
@@ -51,6 +51,11 @@
#define user_siginfo_t siginfo_t
#endif
/* That's for binfmt_elf_fdpic to deal with */
#ifndef elf_check_fdpic
#define elf_check_fdpic(ex) false
#endif
static
int
load_elf_binary
(
struct
linux_binprm
*
bprm
);
static
unsigned
long
elf_map
(
struct
file
*
,
unsigned
long
,
struct
elf_phdr
*
,
int
,
int
,
unsigned
long
);
...
...
@@ -541,7 +546,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
if
(
interp_elf_ex
->
e_type
!=
ET_EXEC
&&
interp_elf_ex
->
e_type
!=
ET_DYN
)
goto
out
;
if
(
!
elf_check_arch
(
interp_elf_ex
))
if
(
!
elf_check_arch
(
interp_elf_ex
)
||
elf_check_fdpic
(
interp_elf_ex
))
goto
out
;
if
(
!
interpreter
->
f_op
->
mmap
)
goto
out
;
...
...
@@ -718,6 +724,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
goto
out
;
if
(
!
elf_check_arch
(
&
loc
->
elf_ex
))
goto
out
;
if
(
elf_check_fdpic
(
&
loc
->
elf_ex
))
goto
out
;
if
(
!
bprm
->
file
->
f_op
->
mmap
)
goto
out
;
...
...
@@ -817,7 +825,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
if
(
memcmp
(
loc
->
interp_elf_ex
.
e_ident
,
ELFMAG
,
SELFMAG
)
!=
0
)
goto
out_free_dentry
;
/* Verify the interpreter has a valid arch */
if
(
!
elf_check_arch
(
&
loc
->
interp_elf_ex
))
if
(
!
elf_check_arch
(
&
loc
->
interp_elf_ex
)
||
elf_check_fdpic
(
&
loc
->
interp_elf_ex
))
goto
out_free_dentry
;
/* Load the interpreter program headers */
...
...
@@ -1190,6 +1199,8 @@ static int load_elf_library(struct file *file)
if
(
elf_ex
.
e_type
!=
ET_EXEC
||
elf_ex
.
e_phnum
>
2
||
!
elf_check_arch
(
&
elf_ex
)
||
!
file
->
f_op
->
mmap
)
goto
out
;
if
(
elf_check_fdpic
(
&
elf_ex
))
goto
out
;
/* Now read in all of the header information */
...
...
fs/binfmt_elf_fdpic.c
View file @
02196144
...
...
@@ -378,6 +378,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
executable_stack
);
if
(
retval
<
0
)
goto
error
;
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
retval
=
arch_setup_additional_pages
(
bprm
,
!!
interpreter_name
);
if
(
retval
<
0
)
goto
error
;
#endif
#endif
/* load the executable and interpreter into memory */
...
...
@@ -831,6 +836,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
if
(
phdr
->
p_vaddr
>=
seg
->
p_vaddr
&&
phdr
->
p_vaddr
+
phdr
->
p_memsz
<=
seg
->
p_vaddr
+
seg
->
p_memsz
)
{
Elf32_Dyn
__user
*
dyn
;
Elf32_Sword
d_tag
;
params
->
dynamic_addr
=
(
phdr
->
p_vaddr
-
seg
->
p_vaddr
)
+
seg
->
addr
;
...
...
@@ -843,8 +851,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
goto
dynamic_error
;
tmp
=
phdr
->
p_memsz
/
sizeof
(
Elf32_Dyn
);
if
(((
Elf32_Dyn
*
)
params
->
dynamic_addr
)[
tmp
-
1
].
d_tag
!=
0
)
dyn
=
(
Elf32_Dyn
__user
*
)
params
->
dynamic_addr
;
__get_user
(
d_tag
,
&
dyn
[
tmp
-
1
].
d_tag
);
if
(
d_tag
!=
0
)
goto
dynamic_error
;
break
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment