Skip to content

Commit

Permalink
Merge branches 'fixes' and 'misc' into for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Russell King committed Apr 26, 2017
2 parents 6d80594 + 11ce4b3 commit c92a90a
Show file tree
Hide file tree
Showing 16 changed files with 210 additions and 57 deletions.
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/arm/l2c2x0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ Optional properties:
- arm,standby-mode: L2 standby mode enable. Value <0> (forcibly disable),
<1> (forcibly enable), property absent (OS specific behavior,
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:

Expand Down
1 change: 1 addition & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ config ARM
select GENERIC_ALLOCATOR
select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CPU_AUTOPROBE
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IRQ_PROBE
Expand Down
11 changes: 11 additions & 0 deletions arch/arm/boot/dts/r7s72100.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@
compatible = "arm,cortex-a9";
reg = <0>;
clock-frequency = <400000000>;
next-level-cache = <&L2>;
};
};

Expand Down Expand Up @@ -368,6 +369,16 @@
<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 {
#address-cells = <1>;
#size-cells = <0>;
Expand Down
38 changes: 38 additions & 0 deletions arch/arm/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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
2 changes: 1 addition & 1 deletion arch/arm/include/asm/fixmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_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)

/* Used by set_fixmap_(io|nocache), both meant for mapping a device */
Expand Down
9 changes: 7 additions & 2 deletions arch/arm/include/asm/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ enum {
};
#endif

struct mod_plt_sec {
struct elf32_shdr *plt;
int plt_count;
};

struct mod_arch_specific {
#ifdef CONFIG_ARM_UNWIND
struct unwind_table *unwind[ARM_SEC_MAX];
#endif
#ifdef CONFIG_ARM_MODULE_PLTS
struct elf32_shdr *plt;
int plt_count;
struct mod_plt_sec core;
struct mod_plt_sec init;
#endif
};

Expand Down
11 changes: 6 additions & 5 deletions arch/arm/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@
#endif

#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)
{
Expand All @@ -51,6 +46,12 @@ void arch_ftrace_update_code(int command)
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)
{
return rec->arch.old_mcount ? OLD_NOP : NOP;
Expand Down
87 changes: 60 additions & 27 deletions arch/arm/kernel/module-plts.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* 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
* it under the terms of the GNU General Public License version 2 as
Expand Down Expand Up @@ -31,19 +31,27 @@ struct plt_entries {
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)
{
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;

/*
* Look for an existing entry pointing to 'val'. Given that the
* relocations are sorted, this will be the last entry we allocated.
* (if one exists).
*/
if (mod->arch.plt_count > 0) {
plt += (mod->arch.plt_count - 1) / PLT_ENT_COUNT;
idx = (mod->arch.plt_count - 1) % PLT_ENT_COUNT;
if (pltsec->plt_count > 0) {
plt += (pltsec->plt_count - 1) / PLT_ENT_COUNT;
idx = (pltsec->plt_count - 1) % PLT_ENT_COUNT;

if (plt->lit[idx] == val)
return (u32)&plt->ldr[idx];
Expand All @@ -53,8 +61,8 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
plt++;
}

mod->arch.plt_count++;
BUG_ON(mod->arch.plt_count * PLT_ENT_SIZE > mod->arch.plt->sh_size);
pltsec->plt_count++;
BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > pltsec->plt->sh_size);

if (!idx)
/* Populate a new set of entries */
Expand Down Expand Up @@ -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 */
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;
const Elf32_Sym *s;
Expand All @@ -144,13 +152,17 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
case R_ARM_THM_JUMP24:
/*
* We only have to consider branch targets that resolve
* to undefined symbols. This is not simply a heuristic,
* it is a fundamental limitation, since the PLT itself
* is part of the module, and needs to be within range
* as well, so modules can never grow beyond that limit.
* to symbols that are defined in a different section.
* This is not simply a heuristic, it is a fundamental
* limitation, since there is no guaranteed way to emit
* 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);
if (s->st_shndx != SHN_UNDEF)
if (s->st_shndx == dstidx)
break;

/*
Expand All @@ -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
* take them into consideration when trying to optimize
* 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) ||
!duplicate_rel(base, rel, i))
Expand All @@ -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,
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_Sym *syms = NULL;

Expand All @@ -184,13 +202,15 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
*/
for (s = sechdrs; s < sechdrs_end; ++s) {
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)
syms = (Elf32_Sym *)s->sh_addr;
}

if (!mod->arch.plt) {
pr_err("%s: module PLT section missing\n", mod->name);
if (!mod->arch.core.plt || !mod->arch.init.plt) {
pr_err("%s: module PLT section(s) missing\n", mod->name);
return -ENOEXEC;
}
if (!syms) {
Expand All @@ -213,16 +233,29 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
/* sort by type and symbol index */
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.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
mod->arch.plt->sh_addralign = L1_CACHE_BYTES;
mod->arch.plt->sh_size = round_up(plts * PLT_ENT_SIZE,
sizeof(struct plt_entries));
mod->arch.plt_count = 0;

pr_debug("%s: plt=%x\n", __func__, mod->arch.plt->sh_size);
mod->arch.core.plt->sh_type = SHT_NOBITS;
mod->arch.core.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
mod->arch.core.plt->sh_addralign = L1_CACHE_BYTES;
mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE,
sizeof(struct plt_entries));
mod->arch.core.plt_count = 0;

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;
}
1 change: 1 addition & 0 deletions arch/arm/kernel/module.lds
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SECTIONS {
.plt : { BYTE(0) }
.init.plt : { BYTE(0) }
}
4 changes: 2 additions & 2 deletions arch/arm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ __setup("fpe=", fpe_setup);

extern void init_default_cache_policy(unsigned long);
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 enum reboot_mode reboot_mode;
extern void setup_dma_zone(const struct machine_desc *desc);
Expand Down Expand Up @@ -1088,7 +1088,7 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();

#ifdef CONFIG_MMU
early_paging_init(mdesc);
early_mm_init(mdesc);
#endif
setup_dma_zone(mdesc);
xen_early_init();
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/mach-shmobile/setup-r7s72100.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ static const char *const r7s72100_boards_compat_dt[] __initconst = {
};

DT_MACHINE_START(R7S72100_DT, "Generic R7S72100 (Flattened Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.init_early = shmobile_init_delay,
.init_late = shmobile_init_late,
.dt_compat = r7s72100_boards_compat_dt,
Expand Down
13 changes: 11 additions & 2 deletions arch/arm/mm/cache-l2x0.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;

struct l2x0_regs l2x0_saved_regs;

static bool l2x0_bresp_disable;
static bool l2x0_flz_disable;

/*
* Common code for all cache controllers.
*/
Expand Down Expand Up @@ -620,7 +623,7 @@ static void __init l2c310_enable(void __iomem *base, unsigned num_lock)
u32 aux = l2x0_saved_regs.aux_ctrl;

if (rev >= L310_CACHE_ID_RTL_R2P0) {
if (cortex_a9) {
if (cortex_a9 && !l2x0_bresp_disable) {
aux |= L310_AUX_CTRL_EARLY_BRESP;
pr_info("L2C-310 enabling early BRESP for Cortex-A9\n");
} else if (aux & L310_AUX_CTRL_EARLY_BRESP) {
Expand All @@ -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 acr = get_auxcr();

Expand Down Expand Up @@ -1200,6 +1203,12 @@ static void __init l2c310_of_parse(const struct device_node *np,
*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;

ret = of_property_read_u32(np, "arm,double-linefill", &val);
Expand Down
Loading

0 comments on commit c92a90a

Please sign in to comment.