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
Kirill Smelkov
linux
Commits
c92a90a5
Commit
c92a90a5
authored
Apr 26, 2017
by
Russell King
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'fixes' and 'misc' into for-next
parents
6d805949
11ce4b33
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
210 additions
and
57 deletions
+210
-57
Documentation/devicetree/bindings/arm/l2c2x0.txt
Documentation/devicetree/bindings/arm/l2c2x0.txt
+3
-0
arch/arm/Kconfig
arch/arm/Kconfig
+1
-0
arch/arm/boot/dts/r7s72100.dtsi
arch/arm/boot/dts/r7s72100.dtsi
+11
-0
arch/arm/include/asm/cpufeature.h
arch/arm/include/asm/cpufeature.h
+38
-0
arch/arm/include/asm/fixmap.h
arch/arm/include/asm/fixmap.h
+1
-1
arch/arm/include/asm/module.h
arch/arm/include/asm/module.h
+7
-2
arch/arm/kernel/ftrace.c
arch/arm/kernel/ftrace.c
+6
-5
arch/arm/kernel/module-plts.c
arch/arm/kernel/module-plts.c
+60
-27
arch/arm/kernel/module.lds
arch/arm/kernel/module.lds
+1
-0
arch/arm/kernel/setup.c
arch/arm/kernel/setup.c
+2
-2
arch/arm/mach-shmobile/setup-r7s72100.c
arch/arm/mach-shmobile/setup-r7s72100.c
+2
-0
arch/arm/mm/cache-l2x0.c
arch/arm/mm/cache-l2x0.c
+11
-2
arch/arm/mm/dump.c
arch/arm/mm/dump.c
+44
-10
arch/arm/mm/init.c
arch/arm/mm/init.c
+8
-5
arch/arm/mm/mmu.c
arch/arm/mm/mmu.c
+13
-3
arch/arm/mm/proc-v7m.S
arch/arm/mm/proc-v7m.S
+2
-0
No files found.
Documentation/devicetree/bindings/arm/l2c2x0.txt
View file @
c92a90a5
...
@@ -90,6 +90,9 @@ Optional properties:
...
@@ -90,6 +90,9 @@ Optional properties:
- arm,standby-mode: L2 standby mode enable. Value <0> (forcibly disable),
- arm,standby-mode: L2 standby mode enable. Value <0> (forcibly disable),
<1> (forcibly enable), property absent (OS specific behavior,
<1> (forcibly enable), property absent (OS specific behavior,
preferably retain firmware settings)
preferably retain firmware settings)
- arm,early-bresp-disable : Disable the CA9 optimization Early BRESP (PL310)
- arm,full-line-zero-disable : Disable the CA9 optimization Full line of zero
write (PL310)
Example:
Example:
...
...
arch/arm/Kconfig
View file @
c92a90a5
...
@@ -27,6 +27,7 @@ config ARM
...
@@ -27,6 +27,7 @@ config ARM
select GENERIC_ALLOCATOR
select GENERIC_ALLOCATOR
select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CPU_AUTOPROBE
select GENERIC_EARLY_IOREMAP
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_PROBE
...
...
arch/arm/boot/dts/r7s72100.dtsi
View file @
c92a90a5
...
@@ -177,6 +177,7 @@ cpu@0 {
...
@@ -177,6 +177,7 @@ cpu@0 {
compatible = "arm,cortex-a9";
compatible = "arm,cortex-a9";
reg = <0>;
reg = <0>;
clock-frequency = <400000000>;
clock-frequency = <400000000>;
next-level-cache = <&L2>;
};
};
};
};
...
@@ -368,6 +369,16 @@ gic: interrupt-controller@e8201000 {
...
@@ -368,6 +369,16 @@ gic: interrupt-controller@e8201000 {
<0xe8202000 0x1000>;
<0xe8202000 0x1000>;
};
};
L2: cache-controller@3ffff000 {
compatible = "arm,pl310-cache";
reg = <0x3ffff000 0x1000>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
arm,early-bresp-disable;
arm,full-line-zero-disable;
cache-unified;
cache-level = <2>;
};
i2c0: i2c@fcfee000 {
i2c0: i2c@fcfee000 {
#address-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
#size-cells = <0>;
...
...
arch/arm/include/asm/cpufeature.h
0 → 100644
View file @
c92a90a5
/*
* Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
*
* 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.
*/
#ifndef __ASM_CPUFEATURE_H
#define __ASM_CPUFEATURE_H
#include <linux/log2.h>
#include <asm/hwcap.h>
/*
* Due to the fact that ELF_HWCAP is a 32-bit type on ARM, and given the number
* of optional CPU features it defines, ARM's CPU hardware capability bits have
* been distributed over separate elf_hwcap and elf_hwcap2 variables, each of
* which covers a subset of the available CPU features.
*
* Currently, only a few of those are suitable for automatic module loading
* (which is the primary use case of this facility) and those happen to be all
* covered by HWCAP2. So let's only cover those via the cpu_feature()
* convenience macro for now (which is used by module_cpu_feature_match()).
* However, all capabilities are exposed via the modalias, and can be matched
* using an explicit MODULE_DEVICE_TABLE() that uses __hwcap_feature() directly.
*/
#define MAX_CPU_FEATURES 64
#define __hwcap_feature(x) ilog2(HWCAP_ ## x)
#define __hwcap2_feature(x) (32 + ilog2(HWCAP2_ ## x))
#define cpu_feature(x) __hwcap2_feature(x)
static
inline
bool
cpu_have_feature
(
unsigned
int
num
)
{
return
num
<
32
?
elf_hwcap
&
BIT
(
num
)
:
elf_hwcap2
&
BIT
(
num
-
32
);
}
#endif
arch/arm/include/asm/fixmap.h
View file @
c92a90a5
...
@@ -41,7 +41,7 @@ static const enum fixed_addresses __end_of_fixed_addresses =
...
@@ -41,7 +41,7 @@ static const enum fixed_addresses __end_of_fixed_addresses =
#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
#define FIXMAP_PAGE_NORMAL (
FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK
)
#define FIXMAP_PAGE_NORMAL (
pgprot_kernel | L_PTE_XN
)
#define FIXMAP_PAGE_RO (FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)
#define FIXMAP_PAGE_RO (FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)
/* Used by set_fixmap_(io|nocache), both meant for mapping a device */
/* Used by set_fixmap_(io|nocache), both meant for mapping a device */
...
...
arch/arm/include/asm/module.h
View file @
c92a90a5
...
@@ -18,13 +18,18 @@ enum {
...
@@ -18,13 +18,18 @@ enum {
};
};
#endif
#endif
struct
mod_plt_sec
{
struct
elf32_shdr
*
plt
;
int
plt_count
;
};
struct
mod_arch_specific
{
struct
mod_arch_specific
{
#ifdef CONFIG_ARM_UNWIND
#ifdef CONFIG_ARM_UNWIND
struct
unwind_table
*
unwind
[
ARM_SEC_MAX
];
struct
unwind_table
*
unwind
[
ARM_SEC_MAX
];
#endif
#endif
#ifdef CONFIG_ARM_MODULE_PLTS
#ifdef CONFIG_ARM_MODULE_PLTS
struct
elf32_shdr
*
plt
;
struct
mod_plt_sec
core
;
int
plt_coun
t
;
struct
mod_plt_sec
ini
t
;
#endif
#endif
};
};
...
...
arch/arm/kernel/ftrace.c
View file @
c92a90a5
...
@@ -29,11 +29,6 @@
...
@@ -29,11 +29,6 @@
#endif
#endif
#ifdef CONFIG_DYNAMIC_FTRACE
#ifdef CONFIG_DYNAMIC_FTRACE
#ifdef CONFIG_OLD_MCOUNT
#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
#define OLD_NOP 0xe1a00000
/* mov r0, r0 */
static
int
__ftrace_modify_code
(
void
*
data
)
static
int
__ftrace_modify_code
(
void
*
data
)
{
{
...
@@ -51,6 +46,12 @@ void arch_ftrace_update_code(int command)
...
@@ -51,6 +46,12 @@ void arch_ftrace_update_code(int command)
stop_machine
(
__ftrace_modify_code
,
&
command
,
NULL
);
stop_machine
(
__ftrace_modify_code
,
&
command
,
NULL
);
}
}
#ifdef CONFIG_OLD_MCOUNT
#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
#define OLD_NOP 0xe1a00000
/* mov r0, r0 */
static
unsigned
long
ftrace_nop_replace
(
struct
dyn_ftrace
*
rec
)
static
unsigned
long
ftrace_nop_replace
(
struct
dyn_ftrace
*
rec
)
{
{
return
rec
->
arch
.
old_mcount
?
OLD_NOP
:
NOP
;
return
rec
->
arch
.
old_mcount
?
OLD_NOP
:
NOP
;
...
...
arch/arm/kernel/module-plts.c
View file @
c92a90a5
/*
/*
* Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
* Copyright (C) 2014
-2017
Linaro Ltd. <ard.biesheuvel@linaro.org>
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License version 2 as
...
@@ -31,9 +31,17 @@ struct plt_entries {
...
@@ -31,9 +31,17 @@ struct plt_entries {
u32
lit
[
PLT_ENT_COUNT
];
u32
lit
[
PLT_ENT_COUNT
];
};
};
static
bool
in_init
(
const
struct
module
*
mod
,
unsigned
long
loc
)
{
return
loc
-
(
u32
)
mod
->
init_layout
.
base
<
mod
->
init_layout
.
size
;
}
u32
get_module_plt
(
struct
module
*
mod
,
unsigned
long
loc
,
Elf32_Addr
val
)
u32
get_module_plt
(
struct
module
*
mod
,
unsigned
long
loc
,
Elf32_Addr
val
)
{
{
struct
plt_entries
*
plt
=
(
struct
plt_entries
*
)
mod
->
arch
.
plt
->
sh_addr
;
struct
mod_plt_sec
*
pltsec
=
!
in_init
(
mod
,
loc
)
?
&
mod
->
arch
.
core
:
&
mod
->
arch
.
init
;
struct
plt_entries
*
plt
=
(
struct
plt_entries
*
)
pltsec
->
plt
->
sh_addr
;
int
idx
=
0
;
int
idx
=
0
;
/*
/*
...
@@ -41,9 +49,9 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
...
@@ -41,9 +49,9 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
* relocations are sorted, this will be the last entry we allocated.
* relocations are sorted, this will be the last entry we allocated.
* (if one exists).
* (if one exists).
*/
*/
if
(
mod
->
arch
.
plt_count
>
0
)
{
if
(
pltsec
->
plt_count
>
0
)
{
plt
+=
(
mod
->
arch
.
plt_count
-
1
)
/
PLT_ENT_COUNT
;
plt
+=
(
pltsec
->
plt_count
-
1
)
/
PLT_ENT_COUNT
;
idx
=
(
mod
->
arch
.
plt_count
-
1
)
%
PLT_ENT_COUNT
;
idx
=
(
pltsec
->
plt_count
-
1
)
%
PLT_ENT_COUNT
;
if
(
plt
->
lit
[
idx
]
==
val
)
if
(
plt
->
lit
[
idx
]
==
val
)
return
(
u32
)
&
plt
->
ldr
[
idx
];
return
(
u32
)
&
plt
->
ldr
[
idx
];
...
@@ -53,8 +61,8 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
...
@@ -53,8 +61,8 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
plt
++
;
plt
++
;
}
}
mod
->
arch
.
plt_count
++
;
pltsec
->
plt_count
++
;
BUG_ON
(
mod
->
arch
.
plt_count
*
PLT_ENT_SIZE
>
mod
->
arch
.
plt
->
sh_size
);
BUG_ON
(
pltsec
->
plt_count
*
PLT_ENT_SIZE
>
pltsec
->
plt
->
sh_size
);
if
(
!
idx
)
if
(
!
idx
)
/* Populate a new set of entries */
/* Populate a new set of entries */
...
@@ -129,7 +137,7 @@ static bool duplicate_rel(Elf32_Addr base, const Elf32_Rel *rel, int num)
...
@@ -129,7 +137,7 @@ static bool duplicate_rel(Elf32_Addr base, const Elf32_Rel *rel, int num)
/* Count how many PLT entries we may need */
/* Count how many PLT entries we may need */
static
unsigned
int
count_plts
(
const
Elf32_Sym
*
syms
,
Elf32_Addr
base
,
static
unsigned
int
count_plts
(
const
Elf32_Sym
*
syms
,
Elf32_Addr
base
,
const
Elf32_Rel
*
rel
,
int
num
)
const
Elf32_Rel
*
rel
,
int
num
,
Elf32_Word
dstidx
)
{
{
unsigned
int
ret
=
0
;
unsigned
int
ret
=
0
;
const
Elf32_Sym
*
s
;
const
Elf32_Sym
*
s
;
...
@@ -144,13 +152,17 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
...
@@ -144,13 +152,17 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
case
R_ARM_THM_JUMP24
:
case
R_ARM_THM_JUMP24
:
/*
/*
* We only have to consider branch targets that resolve
* We only have to consider branch targets that resolve
* to undefined symbols. This is not simply a heuristic,
* to symbols that are defined in a different section.
* it is a fundamental limitation, since the PLT itself
* This is not simply a heuristic, it is a fundamental
* is part of the module, and needs to be within range
* limitation, since there is no guaranteed way to emit
* as well, so modules can never grow beyond that limit.
* PLT entries sufficiently close to the branch if the
* section size exceeds the range of a branch
* instruction. So ignore relocations against defined
* symbols if they live in the same section as the
* relocation target.
*/
*/
s
=
syms
+
ELF32_R_SYM
(
rel
[
i
].
r_info
);
s
=
syms
+
ELF32_R_SYM
(
rel
[
i
].
r_info
);
if
(
s
->
st_shndx
!=
SHN_UNDEF
)
if
(
s
->
st_shndx
==
dstidx
)
break
;
break
;
/*
/*
...
@@ -161,7 +173,12 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
...
@@ -161,7 +173,12 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
* So we need to support them, but there is no need to
* So we need to support them, but there is no need to
* take them into consideration when trying to optimize
* take them into consideration when trying to optimize
* this code. So let's only check for duplicates when
* this code. So let's only check for duplicates when
* the addend is zero.
* the addend is zero. (Note that calls into the core
* module via init PLT entries could involve section
* relative symbol references with non-zero addends, for
* which we may end up emitting duplicates, but the init
* PLT is released along with the rest of the .init
* region as soon as module loading completes.)
*/
*/
if
(
!
is_zero_addend_relocation
(
base
,
rel
+
i
)
||
if
(
!
is_zero_addend_relocation
(
base
,
rel
+
i
)
||
!
duplicate_rel
(
base
,
rel
,
i
))
!
duplicate_rel
(
base
,
rel
,
i
))
...
@@ -174,7 +191,8 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
...
@@ -174,7 +191,8 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
int
module_frob_arch_sections
(
Elf_Ehdr
*
ehdr
,
Elf_Shdr
*
sechdrs
,
int
module_frob_arch_sections
(
Elf_Ehdr
*
ehdr
,
Elf_Shdr
*
sechdrs
,
char
*
secstrings
,
struct
module
*
mod
)
char
*
secstrings
,
struct
module
*
mod
)
{
{
unsigned
long
plts
=
0
;
unsigned
long
core_plts
=
0
;
unsigned
long
init_plts
=
0
;
Elf32_Shdr
*
s
,
*
sechdrs_end
=
sechdrs
+
ehdr
->
e_shnum
;
Elf32_Shdr
*
s
,
*
sechdrs_end
=
sechdrs
+
ehdr
->
e_shnum
;
Elf32_Sym
*
syms
=
NULL
;
Elf32_Sym
*
syms
=
NULL
;
...
@@ -184,13 +202,15 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
...
@@ -184,13 +202,15 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
*/
*/
for
(
s
=
sechdrs
;
s
<
sechdrs_end
;
++
s
)
{
for
(
s
=
sechdrs
;
s
<
sechdrs_end
;
++
s
)
{
if
(
strcmp
(
".plt"
,
secstrings
+
s
->
sh_name
)
==
0
)
if
(
strcmp
(
".plt"
,
secstrings
+
s
->
sh_name
)
==
0
)
mod
->
arch
.
plt
=
s
;
mod
->
arch
.
core
.
plt
=
s
;
else
if
(
strcmp
(
".init.plt"
,
secstrings
+
s
->
sh_name
)
==
0
)
mod
->
arch
.
init
.
plt
=
s
;
else
if
(
s
->
sh_type
==
SHT_SYMTAB
)
else
if
(
s
->
sh_type
==
SHT_SYMTAB
)
syms
=
(
Elf32_Sym
*
)
s
->
sh_addr
;
syms
=
(
Elf32_Sym
*
)
s
->
sh_addr
;
}
}
if
(
!
mod
->
arch
.
plt
)
{
if
(
!
mod
->
arch
.
core
.
plt
||
!
mod
->
arch
.
init
.
plt
)
{
pr_err
(
"%s: module PLT section missing
\n
"
,
mod
->
name
);
pr_err
(
"%s: module PLT section
(s)
missing
\n
"
,
mod
->
name
);
return
-
ENOEXEC
;
return
-
ENOEXEC
;
}
}
if
(
!
syms
)
{
if
(
!
syms
)
{
...
@@ -213,16 +233,29 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
...
@@ -213,16 +233,29 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
/* sort by type and symbol index */
/* sort by type and symbol index */
sort
(
rels
,
numrels
,
sizeof
(
Elf32_Rel
),
cmp_rel
,
NULL
);
sort
(
rels
,
numrels
,
sizeof
(
Elf32_Rel
),
cmp_rel
,
NULL
);
plts
+=
count_plts
(
syms
,
dstsec
->
sh_addr
,
rels
,
numrels
);
if
(
strncmp
(
secstrings
+
dstsec
->
sh_name
,
".init"
,
5
)
!=
0
)
core_plts
+=
count_plts
(
syms
,
dstsec
->
sh_addr
,
rels
,
numrels
,
s
->
sh_info
);
else
init_plts
+=
count_plts
(
syms
,
dstsec
->
sh_addr
,
rels
,
numrels
,
s
->
sh_info
);
}
}
mod
->
arch
.
plt
->
sh_type
=
SHT_NOBITS
;
mod
->
arch
.
core
.
plt
->
sh_type
=
SHT_NOBITS
;
mod
->
arch
.
plt
->
sh_flags
=
SHF_EXECINSTR
|
SHF_ALLOC
;
mod
->
arch
.
core
.
plt
->
sh_flags
=
SHF_EXECINSTR
|
SHF_ALLOC
;
mod
->
arch
.
plt
->
sh_addralign
=
L1_CACHE_BYTES
;
mod
->
arch
.
core
.
plt
->
sh_addralign
=
L1_CACHE_BYTES
;
mod
->
arch
.
plt
->
sh_size
=
round_up
(
plts
*
PLT_ENT_SIZE
,
mod
->
arch
.
core
.
plt
->
sh_size
=
round_up
(
core_plts
*
PLT_ENT_SIZE
,
sizeof
(
struct
plt_entries
));
sizeof
(
struct
plt_entries
));
mod
->
arch
.
plt_count
=
0
;
mod
->
arch
.
core
.
plt_count
=
0
;
pr_debug
(
"%s: plt=%x
\n
"
,
__func__
,
mod
->
arch
.
plt
->
sh_size
);
mod
->
arch
.
init
.
plt
->
sh_type
=
SHT_NOBITS
;
mod
->
arch
.
init
.
plt
->
sh_flags
=
SHF_EXECINSTR
|
SHF_ALLOC
;
mod
->
arch
.
init
.
plt
->
sh_addralign
=
L1_CACHE_BYTES
;
mod
->
arch
.
init
.
plt
->
sh_size
=
round_up
(
init_plts
*
PLT_ENT_SIZE
,
sizeof
(
struct
plt_entries
));
mod
->
arch
.
init
.
plt_count
=
0
;
pr_debug
(
"%s: plt=%x, init.plt=%x
\n
"
,
__func__
,
mod
->
arch
.
core
.
plt
->
sh_size
,
mod
->
arch
.
init
.
plt
->
sh_size
);
return
0
;
return
0
;
}
}
arch/arm/kernel/module.lds
View file @
c92a90a5
SECTIONS {
SECTIONS {
.plt : { BYTE(0) }
.plt : { BYTE(0) }
.init.plt : { BYTE(0) }
}
}
arch/arm/kernel/setup.c
View file @
c92a90a5
...
@@ -80,7 +80,7 @@ __setup("fpe=", fpe_setup);
...
@@ -80,7 +80,7 @@ __setup("fpe=", fpe_setup);
extern
void
init_default_cache_policy
(
unsigned
long
);
extern
void
init_default_cache_policy
(
unsigned
long
);
extern
void
paging_init
(
const
struct
machine_desc
*
desc
);
extern
void
paging_init
(
const
struct
machine_desc
*
desc
);
extern
void
early_
paging
_init
(
const
struct
machine_desc
*
);
extern
void
early_
mm
_init
(
const
struct
machine_desc
*
);
extern
void
adjust_lowmem_bounds
(
void
);
extern
void
adjust_lowmem_bounds
(
void
);
extern
enum
reboot_mode
reboot_mode
;
extern
enum
reboot_mode
reboot_mode
;
extern
void
setup_dma_zone
(
const
struct
machine_desc
*
desc
);
extern
void
setup_dma_zone
(
const
struct
machine_desc
*
desc
);
...
@@ -1088,7 +1088,7 @@ void __init setup_arch(char **cmdline_p)
...
@@ -1088,7 +1088,7 @@ void __init setup_arch(char **cmdline_p)
parse_early_param
();
parse_early_param
();
#ifdef CONFIG_MMU
#ifdef CONFIG_MMU
early_
paging
_init
(
mdesc
);
early_
mm
_init
(
mdesc
);
#endif
#endif
setup_dma_zone
(
mdesc
);
setup_dma_zone
(
mdesc
);
xen_early_init
();
xen_early_init
();
...
...
arch/arm/mach-shmobile/setup-r7s72100.c
View file @
c92a90a5
...
@@ -26,6 +26,8 @@ static const char *const r7s72100_boards_compat_dt[] __initconst = {
...
@@ -26,6 +26,8 @@ static const char *const r7s72100_boards_compat_dt[] __initconst = {
};
};
DT_MACHINE_START
(
R7S72100_DT
,
"Generic R7S72100 (Flattened Device Tree)"
)
DT_MACHINE_START
(
R7S72100_DT
,
"Generic R7S72100 (Flattened Device Tree)"
)
.
l2c_aux_val
=
0
,
.
l2c_aux_mask
=
~
0
,
.
init_early
=
shmobile_init_delay
,
.
init_early
=
shmobile_init_delay
,
.
init_late
=
shmobile_init_late
,
.
init_late
=
shmobile_init_late
,
.
dt_compat
=
r7s72100_boards_compat_dt
,
.
dt_compat
=
r7s72100_boards_compat_dt
,
...
...
arch/arm/mm/cache-l2x0.c
View file @
c92a90a5
...
@@ -57,6 +57,9 @@ static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
...
@@ -57,6 +57,9 @@ static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
struct
l2x0_regs
l2x0_saved_regs
;
struct
l2x0_regs
l2x0_saved_regs
;
static
bool
l2x0_bresp_disable
;
static
bool
l2x0_flz_disable
;
/*
/*
* Common code for all cache controllers.
* Common code for all cache controllers.
*/
*/
...
@@ -620,7 +623,7 @@ static void __init l2c310_enable(void __iomem *base, unsigned num_lock)
...
@@ -620,7 +623,7 @@ static void __init l2c310_enable(void __iomem *base, unsigned num_lock)
u32
aux
=
l2x0_saved_regs
.
aux_ctrl
;
u32
aux
=
l2x0_saved_regs
.
aux_ctrl
;
if
(
rev
>=
L310_CACHE_ID_RTL_R2P0
)
{
if
(
rev
>=
L310_CACHE_ID_RTL_R2P0
)
{
if
(
cortex_a9
)
{
if
(
cortex_a9
&&
!
l2x0_bresp_disable
)
{
aux
|=
L310_AUX_CTRL_EARLY_BRESP
;
aux
|=
L310_AUX_CTRL_EARLY_BRESP
;
pr_info
(
"L2C-310 enabling early BRESP for Cortex-A9
\n
"
);
pr_info
(
"L2C-310 enabling early BRESP for Cortex-A9
\n
"
);
}
else
if
(
aux
&
L310_AUX_CTRL_EARLY_BRESP
)
{
}
else
if
(
aux
&
L310_AUX_CTRL_EARLY_BRESP
)
{
...
@@ -629,7 +632,7 @@ static void __init l2c310_enable(void __iomem *base, unsigned num_lock)
...
@@ -629,7 +632,7 @@ static void __init l2c310_enable(void __iomem *base, unsigned num_lock)
}
}
}
}
if
(
cortex_a9
)
{
if
(
cortex_a9
&&
!
l2x0_flz_disable
)
{
u32
aux_cur
=
readl_relaxed
(
base
+
L2X0_AUX_CTRL
);
u32
aux_cur
=
readl_relaxed
(
base
+
L2X0_AUX_CTRL
);
u32
acr
=
get_auxcr
();
u32
acr
=
get_auxcr
();
...
@@ -1200,6 +1203,12 @@ static void __init l2c310_of_parse(const struct device_node *np,
...
@@ -1200,6 +1203,12 @@ static void __init l2c310_of_parse(const struct device_node *np,
*
aux_mask
&=
~
L2C_AUX_CTRL_PARITY_ENABLE
;
*
aux_mask
&=
~
L2C_AUX_CTRL_PARITY_ENABLE
;
}
}
if
(
of_property_read_bool
(
np
,
"arm,early-bresp-disable"
))
l2x0_bresp_disable
=
true
;
if
(
of_property_read_bool
(
np
,
"arm,full-line-zero-disable"
))
l2x0_flz_disable
=
true
;
prefetch
=
l2x0_saved_regs
.
prefetch_ctrl
;
prefetch
=
l2x0_saved_regs
.
prefetch_ctrl
;
ret
=
of_property_read_u32
(
np
,
"arm,double-linefill"
,
&
val
);
ret
=
of_property_read_u32
(
np
,
"arm,double-linefill"
,
&
val
);
...
...
arch/arm/mm/dump.c
View file @
c92a90a5
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include <asm/domain.h>
#include <asm/fixmap.h>
#include <asm/fixmap.h>
#include <asm/memory.h>
#include <asm/memory.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
...
@@ -43,6 +44,7 @@ struct pg_state {
...
@@ -43,6 +44,7 @@ struct pg_state {
unsigned
long
start_address
;
unsigned
long
start_address
;
unsigned
level
;
unsigned
level
;
u64
current_prot
;
u64
current_prot
;
const
char
*
current_domain
;
};
};
struct
prot_bits
{
struct
prot_bits
{
...
@@ -216,7 +218,8 @@ static void dump_prot(struct pg_state *st, const struct prot_bits *bits, size_t
...
@@ -216,7 +218,8 @@ static void dump_prot(struct pg_state *st, const struct prot_bits *bits, size_t
}
}
}
}
static
void
note_page
(
struct
pg_state
*
st
,
unsigned
long
addr
,
unsigned
level
,
u64
val
)
static
void
note_page
(
struct
pg_state
*
st
,
unsigned
long
addr
,
unsigned
int
level
,
u64
val
,
const
char
*
domain
)
{
{
static
const
char
units
[]
=
"KMGTPE"
;
static
const
char
units
[]
=
"KMGTPE"
;
u64
prot
=
val
&
pg_level
[
level
].
mask
;
u64
prot
=
val
&
pg_level
[
level
].
mask
;
...
@@ -224,8 +227,10 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u
...
@@ -224,8 +227,10 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u
if
(
!
st
->
level
)
{
if
(
!
st
->
level
)
{
st
->
level
=
level
;
st
->
level
=
level
;
st
->
current_prot
=
prot
;
st
->
current_prot
=
prot
;
st
->
current_domain
=
domain
;
seq_printf
(
st
->
seq
,
"---[ %s ]---
\n
"
,
st
->
marker
->
name
);
seq_printf
(
st
->
seq
,
"---[ %s ]---
\n
"
,
st
->
marker
->
name
);
}
else
if
(
prot
!=
st
->
current_prot
||
level
!=
st
->
level
||
}
else
if
(
prot
!=
st
->
current_prot
||
level
!=
st
->
level
||
domain
!=
st
->
current_domain
||
addr
>=
st
->
marker
[
1
].
start_address
)
{
addr
>=
st
->
marker
[
1
].
start_address
)
{
const
char
*
unit
=
units
;
const
char
*
unit
=
units
;
unsigned
long
delta
;
unsigned
long
delta
;
...
@@ -240,6 +245,8 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u
...
@@ -240,6 +245,8 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u
unit
++
;
unit
++
;
}
}
seq_printf
(
st
->
seq
,
"%9lu%c"
,
delta
,
*
unit
);
seq_printf
(
st
->
seq
,
"%9lu%c"
,
delta
,
*
unit
);
if
(
st
->
current_domain
)
seq_printf
(
st
->
seq
,
" %s"
,
st
->
current_domain
);
if
(
pg_level
[
st
->
level
].
bits
)
if
(
pg_level
[
st
->
level
].
bits
)
dump_prot
(
st
,
pg_level
[
st
->
level
].
bits
,
pg_level
[
st
->
level
].
num
);
dump_prot
(
st
,
pg_level
[
st
->
level
].
bits
,
pg_level
[
st
->
level
].
num
);
seq_printf
(
st
->
seq
,
"
\n
"
);
seq_printf
(
st
->
seq
,
"
\n
"
);
...
@@ -251,11 +258,13 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u
...
@@ -251,11 +258,13 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u
}
}
st
->
start_address
=
addr
;
st
->
start_address
=
addr
;
st
->
current_prot
=
prot
;
st
->
current_prot
=
prot
;
st
->
current_domain
=
domain
;
st
->
level
=
level
;
st
->
level
=
level
;
}
}
}
}
static
void
walk_pte
(
struct
pg_state
*
st
,
pmd_t
*
pmd
,
unsigned
long
start
)
static
void
walk_pte
(
struct
pg_state
*
st
,
pmd_t
*
pmd
,
unsigned
long
start
,
const
char
*
domain
)
{
{
pte_t
*
pte
=
pte_offset_kernel
(
pmd
,
0
);
pte_t
*
pte
=
pte_offset_kernel
(
pmd
,
0
);
unsigned
long
addr
;
unsigned
long
addr
;
...
@@ -263,25 +272,50 @@ static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
...
@@ -263,25 +272,50 @@ static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
for
(
i
=
0
;
i
<
PTRS_PER_PTE
;
i
++
,
pte
++
)
{
for
(
i
=
0
;
i
<
PTRS_PER_PTE
;
i
++
,
pte
++
)
{
addr
=
start
+
i
*
PAGE_SIZE
;
addr
=
start
+
i
*
PAGE_SIZE
;
note_page
(
st
,
addr
,
4
,
pte_val
(
*
pte
));
note_page
(
st
,
addr
,
4
,
pte_val
(
*
pte
)
,
domain
);
}
}
}
}
static
const
char
*
get_domain_name
(
pmd_t
*
pmd
)
{
#ifndef CONFIG_ARM_LPAE
switch
(
pmd_val
(
*
pmd
)
&
PMD_DOMAIN_MASK
)
{
case
PMD_DOMAIN
(
DOMAIN_KERNEL
):
return
"KERNEL "
;
case
PMD_DOMAIN
(
DOMAIN_USER
):
return
"USER "
;
case
PMD_DOMAIN
(
DOMAIN_IO
):
return
"IO "
;
case
PMD_DOMAIN
(
DOMAIN_VECTORS
):
return
"VECTORS"
;
default:
return
"unknown"
;
}
#endif
return
NULL
;
}
static
void
walk_pmd
(
struct
pg_state
*
st
,
pud_t
*
pud
,
unsigned
long
start
)
static
void
walk_pmd
(
struct
pg_state
*
st
,
pud_t
*
pud
,
unsigned
long
start
)
{
{
pmd_t
*
pmd
=
pmd_offset
(
pud
,
0
);
pmd_t
*
pmd
=
pmd_offset
(
pud
,
0
);
unsigned
long
addr
;
unsigned
long
addr
;
unsigned
i
;
unsigned
i
;
const
char
*
domain
;
for
(
i
=
0
;
i
<
PTRS_PER_PMD
;
i
++
,
pmd
++
)
{
for
(
i
=
0
;
i
<
PTRS_PER_PMD
;
i
++
,
pmd
++
)
{
addr
=
start
+
i
*
PMD_SIZE
;
addr
=
start
+
i
*
PMD_SIZE
;
domain
=
get_domain_name
(
pmd
);
if
(
pmd_none
(
*
pmd
)
||
pmd_large
(
*
pmd
)
||
!
pmd_present
(
*
pmd
))
if
(
pmd_none
(
*
pmd
)
||
pmd_large
(
*
pmd
)
||
!
pmd_present
(
*
pmd
))
note_page
(
st
,
addr
,
3
,
pmd_val
(
*
pmd
));
note_page
(
st
,
addr
,
3
,
pmd_val
(
*
pmd
)
,
domain
);
else
else
walk_pte
(
st
,
pmd
,
addr
);
walk_pte
(
st
,
pmd
,
addr
,
domain
);
if
(
SECTION_SIZE
<
PMD_SIZE
&&
pmd_large
(
pmd
[
1
]))
if
(
SECTION_SIZE
<
PMD_SIZE
&&
pmd_large
(
pmd
[
1
]))
{
note_page
(
st
,
addr
+
SECTION_SIZE
,
3
,
pmd_val
(
pmd
[
1
]));
addr
+=
SECTION_SIZE
;
pmd
++
;
domain
=
get_domain_name
(
pmd
);
note_page
(
st
,
addr
,
3
,
pmd_val
(
*
pmd
),
domain
);
}
}
}
}
}
...
@@ -296,7 +330,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
...
@@ -296,7 +330,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
if
(
!
pud_none
(
*
pud
))
{
if
(
!
pud_none
(
*
pud
))
{
walk_pmd
(
st
,
pud
,
addr
);
walk_pmd
(
st
,
pud
,
addr
);
}
else
{
}
else
{
note_page
(
st
,
addr
,
2
,
pud_val
(
*
pud
));
note_page
(
st
,
addr
,
2
,
pud_val
(
*
pud
)
,
NULL
);
}
}
}
}
}
}
...
@@ -317,11 +351,11 @@ static void walk_pgd(struct seq_file *m)
...
@@ -317,11 +351,11 @@ static void walk_pgd(struct seq_file *m)
if
(
!
pgd_none
(
*
pgd
))
{
if
(
!
pgd_none
(
*
pgd
))
{
walk_pud
(
&
st
,
pgd
,
addr
);
walk_pud
(
&
st
,
pgd
,
addr
);
}
else
{
}
else
{
note_page
(
&
st
,
addr
,
1
,
pgd_val
(
*
pgd
));
note_page
(
&
st
,
addr
,
1
,
pgd_val
(
*
pgd
)
,
NULL
);
}
}
}
}
note_page
(
&
st
,
0
,
0
,
0
);
note_page
(
&
st
,
0
,
0
,
0
,
NULL
);
}
}
static
int
ptdump_show
(
struct
seq_file
*
m
,
void
*
v
)
static
int
ptdump_show
(
struct
seq_file
*
m
,
void
*
v
)
...
...
arch/arm/mm/init.c
View file @
c92a90a5
...
@@ -709,34 +709,37 @@ void set_section_perms(struct section_perm *perms, int n, bool set,
...
@@ -709,34 +709,37 @@ void set_section_perms(struct section_perm *perms, int n, bool set,
}
}
/**
* update_sections_early intended to be called only through stop_machine
* framework and executed by only one CPU while all other CPUs will spin and
* wait, so no locking is required in this function.
*/
static
void
update_sections_early
(
struct
section_perm
perms
[],
int
n
)
static
void
update_sections_early
(
struct
section_perm
perms
[],
int
n
)
{
{
struct
task_struct
*
t
,
*
s
;
struct
task_struct
*
t
,
*
s
;
read_lock
(
&
tasklist_lock
);
for_each_process
(
t
)
{
for_each_process
(
t
)
{
if
(
t
->
flags
&
PF_KTHREAD
)
if
(
t
->
flags
&
PF_KTHREAD
)
continue
;
continue
;
for_each_thread
(
t
,
s
)
for_each_thread
(
t
,
s
)
set_section_perms
(
perms
,
n
,
true
,
s
->
mm
);
set_section_perms
(
perms
,
n
,
true
,
s
->
mm
);
}
}
read_unlock
(
&
tasklist_lock
);
set_section_perms
(
perms
,
n
,
true
,
current
->
active_mm
);
set_section_perms
(
perms
,
n
,
true
,
current
->
active_mm
);
set_section_perms
(
perms
,
n
,
true
,
&
init_mm
);
set_section_perms
(
perms
,
n
,
true
,
&
init_mm
);
}
}
int
__fix_kernmem_perms
(
void
*
unused
)
static
int
__fix_kernmem_perms
(
void
*
unused
)
{
{
update_sections_early
(
nx_perms
,
ARRAY_SIZE
(
nx_perms
));
update_sections_early
(
nx_perms
,
ARRAY_SIZE
(
nx_perms
));
return
0
;
return
0
;
}
}
void
fix_kernmem_perms
(
void
)
static
void
fix_kernmem_perms
(
void
)
{
{
stop_machine
(
__fix_kernmem_perms
,
NULL
,
NULL
);
stop_machine
(
__fix_kernmem_perms
,
NULL
,
NULL
);
}
}
int
__mark_rodata_ro
(
void
*
unused
)
static
int
__mark_rodata_ro
(
void
*
unused
)
{
{
update_sections_early
(
ro_perms
,
ARRAY_SIZE
(
ro_perms
));
update_sections_early
(
ro_perms
,
ARRAY_SIZE
(
ro_perms
));
return
0
;
return
0
;
...
...
arch/arm/mm/mmu.c
View file @
c92a90a5
...
@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
...
@@ -414,6 +414,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
FIXADDR_END
);
FIXADDR_END
);
BUG_ON
(
idx
>=
__end_of_fixed_addresses
);
BUG_ON
(
idx
>=
__end_of_fixed_addresses
);
/* we only support device mappings until pgprot_kernel has been set */
if
(
WARN_ON
(
pgprot_val
(
prot
)
!=
pgprot_val
(
FIXMAP_PAGE_IO
)
&&
pgprot_val
(
pgprot_kernel
)
==
0
))
return
;
if
(
pgprot_val
(
prot
))
if
(
pgprot_val
(
prot
))
set_pte_at
(
NULL
,
vaddr
,
pte
,
set_pte_at
(
NULL
,
vaddr
,
pte
,
pfn_pte
(
phys
>>
PAGE_SHIFT
,
prot
));
pfn_pte
(
phys
>>
PAGE_SHIFT
,
prot
));
...
@@ -1492,7 +1497,7 @@ pgtables_remap lpae_pgtables_remap_asm;
...
@@ -1492,7 +1497,7 @@ pgtables_remap lpae_pgtables_remap_asm;
* early_paging_init() recreates boot time page table setup, allowing machines
* early_paging_init() recreates boot time page table setup, allowing machines
* to switch over to a high (>4G) address space on LPAE systems
* to switch over to a high (>4G) address space on LPAE systems
*/
*/
void
__init
early_paging_init
(
const
struct
machine_desc
*
mdesc
)
static
void
__init
early_paging_init
(
const
struct
machine_desc
*
mdesc
)
{
{
pgtables_remap
*
lpae_pgtables_remap
;
pgtables_remap
*
lpae_pgtables_remap
;
unsigned
long
pa_pgd
;
unsigned
long
pa_pgd
;
...
@@ -1560,7 +1565,7 @@ void __init early_paging_init(const struct machine_desc *mdesc)
...
@@ -1560,7 +1565,7 @@ void __init early_paging_init(const struct machine_desc *mdesc)
#else
#else
void
__init
early_paging_init
(
const
struct
machine_desc
*
mdesc
)
static
void
__init
early_paging_init
(
const
struct
machine_desc
*
mdesc
)
{
{
long
long
offset
;
long
long
offset
;
...
@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc)
...
@@ -1616,7 +1621,6 @@ void __init paging_init(const struct machine_desc *mdesc)
{
{
void
*
zero_page
;
void
*
zero_page
;
build_mem_type_table
();
prepare_page_table
();
prepare_page_table
();
map_lowmem
();
map_lowmem
();
memblock_set_current_limit
(
arm_lowmem_limit
);
memblock_set_current_limit
(
arm_lowmem_limit
);
...
@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc)
...
@@ -1636,3 +1640,9 @@ void __init paging_init(const struct machine_desc *mdesc)
empty_zero_page
=
virt_to_page
(
zero_page
);
empty_zero_page
=
virt_to_page
(
zero_page
);
__flush_dcache_page
(
NULL
,
empty_zero_page
);
__flush_dcache_page
(
NULL
,
empty_zero_page
);
}
}
void
__init
early_mm_init
(
const
struct
machine_desc
*
mdesc
)
{
build_mem_type_table
();
early_paging_init
(
mdesc
);
}
arch/arm/mm/proc-v7m.S
View file @
c92a90a5
...
@@ -135,9 +135,11 @@ __v7m_setup_cont:
...
@@ -135,9 +135,11 @@ __v7m_setup_cont:
dsb
dsb
mov
r6
,
lr
@
save
LR
mov
r6
,
lr
@
save
LR
ldr
sp
,
=
init_thread_union
+
THREAD_START_SP
ldr
sp
,
=
init_thread_union
+
THREAD_START_SP
stmia
sp
,
{
r0
-
r3
,
r12
}
cpsie
i
cpsie
i
svc
#
0
svc
#
0
1
:
cpsid
i
1
:
cpsid
i
ldmia
sp
,
{
r0
-
r3
,
r12
}
str
r5
,
[
r12
,
#
11
*
4
]
@
restore
the
original
SVC
vector
entry
str
r5
,
[
r12
,
#
11
*
4
]
@
restore
the
original
SVC
vector
entry
mov
lr
,
r6
@
restore
LR
mov
lr
,
r6
@
restore
LR
...
...
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