From 7e66cbc93f876e24c2f8434cf011b94be242005e Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Thu, 28 Aug 2014 12:49:36 +0100 Subject: ARM: 8132/1: LPAE: drop wrong carry flag correction after adding TTBR1_OFFSET ARM: LPAE: drop wrong carry flag correction after adding TTBR1_OFFSET In commit 7fb00c2fca4b6c58be521eb3676cf4b4ba8dde3b ("ARM: 8114/1: LPAE: load upper bits of early TTBR0/TTBR1") part which fixes carrying in adding TTBR1_OFFSET to TTRR1 was wrong: addls ttbr1, ttbr1, #TTBR1_OFFSET adcls tmp, tmp, #0 addls doesn't update flags, adcls adds carry from cmp above: cmp ttbr1, tmp @ PHYS_OFFSET > PAGE_OFFSET? Condition 'ls' means carry flag is clear or zero flag is set, thus only one case is affected: when PHYS_OFFSET == PAGE_OFFSET. It seems safer to remove this fixup. Bug is here for ages and nobody complained. Let's fix it separately. Reported-and-Tested-by: Jassi Brar Signed-off-by: Konstantin Khlebnikov Signed-off-by: Russell King --- arch/arm/mm/proc-v7-3level.S | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S index 1a24e9232ec8..b64e67c7f176 100644 --- a/arch/arm/mm/proc-v7-3level.S +++ b/arch/arm/mm/proc-v7-3level.S @@ -146,7 +146,6 @@ ENDPROC(cpu_v7_set_pte_ext) mov \tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits mov \ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT @ lower bits addls \ttbr1, \ttbr1, #TTBR1_OFFSET - adcls \tmp, \tmp, #0 mcrr p15, 1, \ttbr1, \tmp, c2 @ load TTBR1 mov \tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits mov \ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT @ lower bits -- cgit v1.2.3 From fbf10641487d0c6938e580d143e4519e7ea90acf Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 5 Sep 2014 23:00:33 +0100 Subject: ARM: 8138/1: drop ISAR0 workaround for B15 The Brahma-B15's ISAR0 correcty advertises UDIV/SDIV support in both ARM and Thumb2 modes (CPUID_EXT_ISAR0=02101110), so we don't need to manually apply this hwcap. The code in question actually predates the following commit, which made our hwcaps unnecessary: commit 8164f7af88d9ad3a757bd14f634b23997ee77f6b Author: Stephen Boyd Date: Mon Mar 18 19:44:15 2013 +0100 ARM: 7680/1: Detect support for SDIV/UDIV from ISAR0 register Signed-off-by: Brian Norris Cc: Will Deacon Cc: Mark Rutland Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index b5d67db20897..b3a947863ac7 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -570,7 +570,7 @@ __v7_ca15mp_proc_info: __v7_b15mp_proc_info: .long 0x420f00f0 .long 0xff0ffff0 - __v7_proc __v7_b15mp_setup, hwcaps = HWCAP_IDIV + __v7_proc __v7_b15mp_setup .size __v7_b15mp_proc_info, . - __v7_b15mp_proc_info /* -- cgit v1.2.3 From 2c553ac19e73235b61b67fdc5c14be9913a2758d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 25 Sep 2014 11:39:19 +0100 Subject: ARM: 8164/1: mm: clear SCTLR.HA instead of setting it for LPAE SCTLR.HA (hardware access flag) is deprecated and not actually implemented by any CPUs. Furthermore, it can confuse cr_alignment checks where the whole value of SCTLR is compared against the value sitting in the hardware, since the bit is actually RAZ/WI and will not match the saved cr_alignment value. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/proc-v7-3level.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S index b64e67c7f176..d3daed0ae0ad 100644 --- a/arch/arm/mm/proc-v7-3level.S +++ b/arch/arm/mm/proc-v7-3level.S @@ -157,9 +157,9 @@ ENDPROC(cpu_v7_set_pte_ext) * TFR EV X F IHD LR S * .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced - * 11 0 110 1 0011 1100 .111 1101 < we want + * 11 0 110 0 0011 1100 .111 1101 < we want */ .align 2 .type v7_crval, #object v7_crval: - crval clear=0x0120c302, mmuset=0x30c23c7d, ucset=0x00c01c7c + crval clear=0x0122c302, mmuset=0x30c03c7d, ucset=0x00c01c7c -- cgit v1.2.3 From 5ca918e5e3f9df4634077c06585c42bc6a8d699a Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Thu, 25 Sep 2014 11:56:19 +0100 Subject: ARM: 8165/1: alignment: don't break misaligned NEON load/store The alignment fixup incorrectly decodes faulting ARM VLDn/VSTn instructions (where the optional alignment hint is given but incorrect) as LDR/STR, leading to register corruption. Detect these and correctly treat them as unhandled, so that userspace gets the fault it expects. Reported-by: Simon Hosie Signed-off-by: Robin Murphy Cc: Signed-off-by: Russell King --- arch/arm/mm/alignment.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 0c1ab49e5f7b..83792f4324ea 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -41,6 +41,7 @@ * This code is not portable to processors with late data abort handling. */ #define CODING_BITS(i) (i & 0x0e000000) +#define COND_BITS(i) (i & 0xf0000000) #define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */ #define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ @@ -821,6 +822,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) break; case 0x04000000: /* ldr or str immediate */ + if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */ + goto bad; offset.un = OFFSET_BITS(instr); handler = do_alignment_ldrstr; break; -- cgit v1.2.3 From 8b521cb2947d8811b4cf7fc6a7a6ebde35218243 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 16 Sep 2014 20:41:43 +0100 Subject: ARM: 8152/1: Convert pr_warning to pr_warn Use the more common pr_warn. Other miscellanea: o Coalesce formats o Realign arguments Signed-off-by: Joe Perches Signed-off-by: Russell King --- arch/arm/mm/idmap.c | 2 +- arch/arm/mm/mmu.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index c447ec70e868..e7a81cebbb2e 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -27,7 +27,7 @@ static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, if (pud_none_or_clear_bad(pud) || (pud_val(*pud) & L_PGD_SWAPPER)) { pmd = pmd_alloc_one(&init_mm, addr); if (!pmd) { - pr_warning("Failed to allocate identity pmd.\n"); + pr_warn("Failed to allocate identity pmd.\n"); return; } /* diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 8348ed6b2efe..9f98cec7fe1e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -223,13 +223,13 @@ early_param("ecc", early_ecc); static int __init early_cachepolicy(char *p) { - pr_warning("cachepolicy kernel parameter not supported without cp15\n"); + pr_warn("cachepolicy kernel parameter not supported without cp15\n"); } early_param("cachepolicy", early_cachepolicy); static int __init noalign_setup(char *__unused) { - pr_warning("noalign kernel parameter not supported without cp15\n"); + pr_warn("noalign kernel parameter not supported without cp15\n"); } __setup("noalign", noalign_setup); -- cgit v1.2.3 From f3354ab67476dc800463df32e33423158003d80b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Sep 2014 09:01:58 +0100 Subject: ARM: 8169/1: l2c: parse cache properties from ePAPR definitions When both 'cache-size' and 'cache-sets' are specified for a L2 cache controller node, parse those properties and set up the set size based on which type of L2 cache controller we are using. Update the L2 cache controller Device Tree binding with the optional 'cache-size', 'cache-sets', 'cache-block-size' and 'cache-line-size' properties. These come from the ePAPR specification. Using the cache size, number of sets and cache line size we can calculate desired associativity of the L2 cache. This is done by the calculation: set size = cache size / sets ways = set size / line size way size = cache size / ways = sets * line size associativity = cache size / way size Example output from the PB1176 DT that look like this: L2: l2-cache { compatible = "arm,l220-cache"; (...) arm,override-auxreg; cache-size = <131072>; // 128kB cache-sets = <512>; cache-line-size = <32>; }; Ends up like this: L2C OF: override cache size: 131072 bytes (128KB) L2C OF: override line size: 32 bytes L2C OF: override way size: 16384 bytes (16KB) L2C OF: override associativity: 8 L2C: DT/platform modifies aux control register: 0x02020fff -> 0x02030fff L2C-220 cache controller enabled, 8 ways, 128 kB L2C-220: CACHE_ID 0x41000486, AUX_CTRL 0x06030fff Which is consistent with the value earlier hardcoded for the PB1176 platform. This patch is an extended version based on the initial patch by Florian Fainelli. Reviewed-by: Arnd Bergmann Signed-off-by: Florian Fainelli Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 5f2c988a06ac..55f9d6e0cc88 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -945,6 +946,98 @@ static int l2_wt_override; * pass it though the device tree */ static u32 cache_id_part_number_from_dt; +/** + * l2x0_cache_size_of_parse() - read cache size parameters from DT + * @np: the device tree node for the l2 cache + * @aux_val: pointer to machine-supplied auxilary register value, to + * be augmented by the call (bits to be set to 1) + * @aux_mask: pointer to machine-supplied auxilary register mask, to + * be augmented by the call (bits to be set to 0) + * @associativity: variable to return the calculated associativity in + * @max_way_size: the maximum size in bytes for the cache ways + */ +static void __init l2x0_cache_size_of_parse(const struct device_node *np, + u32 *aux_val, u32 *aux_mask, + u32 *associativity, + u32 max_way_size) +{ + u32 mask = 0, val = 0; + u32 cache_size = 0, sets = 0; + u32 way_size_bits = 1; + u32 way_size = 0; + u32 block_size = 0; + u32 line_size = 0; + + of_property_read_u32(np, "cache-size", &cache_size); + of_property_read_u32(np, "cache-sets", &sets); + of_property_read_u32(np, "cache-block-size", &block_size); + of_property_read_u32(np, "cache-line-size", &line_size); + + if (!cache_size || !sets) + return; + + /* All these l2 caches have the same line = block size actually */ + if (!line_size) { + if (block_size) { + /* If linesize if not given, it is equal to blocksize */ + line_size = block_size; + } else { + /* Fall back to known size */ + pr_warn("L2C OF: no cache block/line size given: " + "falling back to default size %d bytes\n", + CACHE_LINE_SIZE); + line_size = CACHE_LINE_SIZE; + } + } + + if (line_size != CACHE_LINE_SIZE) + pr_warn("L2C OF: DT supplied line size %d bytes does " + "not match hardware line size of %d bytes\n", + line_size, + CACHE_LINE_SIZE); + + /* + * Since: + * set size = cache size / sets + * ways = cache size / (sets * line size) + * way size = cache size / (cache size / (sets * line size)) + * way size = sets * line size + * associativity = ways = cache size / way size + */ + way_size = sets * line_size; + *associativity = cache_size / way_size; + + if (way_size > max_way_size) { + pr_err("L2C OF: set size %dKB is too large\n", way_size); + return; + } + + pr_info("L2C OF: override cache size: %d bytes (%dKB)\n", + cache_size, cache_size >> 10); + pr_info("L2C OF: override line size: %d bytes\n", line_size); + pr_info("L2C OF: override way size: %d bytes (%dKB)\n", + way_size, way_size >> 10); + pr_info("L2C OF: override associativity: %d\n", *associativity); + + /* + * Calculates the bits 17:19 to set for way size: + * 512KB -> 6, 256KB -> 5, ... 16KB -> 1 + */ + way_size_bits = ilog2(way_size >> 10) - 3; + if (way_size_bits < 1 || way_size_bits > 6) { + pr_err("L2C OF: cache way size illegal: %dKB is not mapped\n", + way_size); + return; + } + + mask |= L2C_AUX_CTRL_WAY_SIZE_MASK; + val |= (way_size_bits << L2C_AUX_CTRL_WAY_SIZE_SHIFT); + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + static void __init l2x0_of_parse(const struct device_node *np, u32 *aux_val, u32 *aux_mask) { @@ -952,6 +1045,7 @@ static void __init l2x0_of_parse(const struct device_node *np, u32 tag = 0; u32 dirty = 0; u32 val = 0, mask = 0; + u32 assoc; of_property_read_u32(np, "arm,tag-latency", &tag); if (tag) { @@ -974,6 +1068,15 @@ static void __init l2x0_of_parse(const struct device_node *np, val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; } + l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_256K); + if (assoc > 8) { + pr_err("l2x0 of: cache setting yield too high associativity\n"); + pr_err("l2x0 of: %d calculated, max 8\n", assoc); + } else { + mask |= L2X0_AUX_CTRL_ASSOC_MASK; + val |= (assoc << L2X0_AUX_CTRL_ASSOC_SHIFT); + } + *aux_val &= ~mask; *aux_val |= val; *aux_mask &= ~mask; @@ -1021,6 +1124,7 @@ static void __init l2c310_of_parse(const struct device_node *np, u32 data[3] = { 0, 0, 0 }; u32 tag[3] = { 0, 0, 0 }; u32 filter[2] = { 0, 0 }; + u32 assoc; of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); if (tag[0] && tag[1] && tag[2]) @@ -1047,6 +1151,23 @@ static void __init l2c310_of_parse(const struct device_node *np, writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN, l2x0_base + L310_ADDR_FILTER_START); } + + l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K); + switch (assoc) { + case 16: + *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK; + *aux_val |= L310_AUX_CTRL_ASSOCIATIVITY_16; + *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK; + break; + case 8: + *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK; + *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK; + break; + default: + pr_err("PL310 OF: cache setting yield illegal associativity\n"); + pr_err("PL310 OF: %d calculated, only 8 and 16 legal\n", assoc); + break; + } } static const struct l2c_init_data of_l2c310_data __initconst = { -- cgit v1.2.3 From 421520ba98290a73b35b7644e877a48f18e06004 Mon Sep 17 00:00:00 2001 From: Yalin Wang Date: Fri, 26 Sep 2014 03:07:09 +0100 Subject: ARM: 8167/1: extend the reserved memory for initrd to be page aligned This patch extends the start and end address of initrd to be page aligned, so that we can free all memory including the un-page aligned head or tail page of initrd, if the start or end address of initrd are not page aligned, the page can't be freed by free_initrd_mem() function. Signed-off-by: Yalin Wang Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/init.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 659c75d808dc..9221645dd192 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -636,6 +636,11 @@ static int keep_initrd; void free_initrd_mem(unsigned long start, unsigned long end) { if (!keep_initrd) { + if (start == initrd_start) + start = round_down(start, PAGE_SIZE); + if (end == initrd_end) + end = round_up(end, PAGE_SIZE); + poison_init_mem((void *)start, PAGE_ALIGN(end) - start); free_reserved_area((void *)start, (void *)end, -1, "initrd"); } -- cgit v1.2.3