From 834020366da9ab3fb87d1eb9a3160eb22dbed63a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 8 Aug 2019 16:51:00 +0100 Subject: ARM: 8898/1: mm: Don't treat faults reported from cache maintenance as writes Translation faults arising from cache maintenance instructions are rather unhelpfully reported with an FSR value where the WnR field is set to 1, indicating that the faulting access was a write. Since cache maintenance instructions on 32-bit ARM do not require any particular permissions, this can cause our private 'cacheflush' system call to fail spuriously if a translation fault is generated due to page aging when targetting a read-only VMA. In this situation, we will return -EFAULT to userspace, although this is unfortunately suppressed by the popular '__builtin___clear_cache()' intrinsic provided by GCC, which returns void. Although it's tempting to write this off as a userspace issue, we can actually do a little bit better on CPUs that support LPAE, even if the short-descriptor format is in use. On these CPUs, cache maintenance faults additionally set the CM field in the FSR, which we can use to suppress the write permission checks in the page fault handler and succeed in performing cache maintenance to read-only areas even in the presence of a translation fault. Reported-by: Orion Hodson Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/fault.c | 4 ++-- arch/arm/mm/fault.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 890eeaac3cbb..bd0f4821f7e1 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -191,7 +191,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma) { unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; - if (fsr & FSR_WRITE) + if ((fsr & FSR_WRITE) && !(fsr & FSR_CM)) mask = VM_WRITE; if (fsr & FSR_LNX_PF) mask = VM_EXEC; @@ -262,7 +262,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (user_mode(regs)) flags |= FAULT_FLAG_USER; - if (fsr & FSR_WRITE) + if ((fsr & FSR_WRITE) && !(fsr & FSR_CM)) flags |= FAULT_FLAG_WRITE; /* diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h index c063708fa503..9ecc2097a87a 100644 --- a/arch/arm/mm/fault.h +++ b/arch/arm/mm/fault.h @@ -6,6 +6,7 @@ * Fault status register encodings. We steal bit 31 for our own purposes. */ #define FSR_LNX_PF (1 << 31) +#define FSR_CM (1 << 13) #define FSR_WRITE (1 << 11) #define FSR_FS4 (1 << 10) #define FSR_FS3_0 (15) -- cgit From 921a3fe5be2dd0aac70405faf32a970716f55e03 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Tue, 27 Aug 2019 21:49:22 +0100 Subject: ARM: 8902/1: l2c: move cache-aurora-l2.h to asm/hardware This include file will be used by the AURORA EDAC code. Signed-off-by: Jan Luebbe Reviewed-by: Gregory CLEMENT Signed-off-by: Chris Packham Signed-off-by: Russell King --- arch/arm/mm/cache-aurora-l2.h | 55 ------------------------------------------- arch/arm/mm/cache-l2x0.c | 2 +- 2 files changed, 1 insertion(+), 56 deletions(-) delete mode 100644 arch/arm/mm/cache-aurora-l2.h (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-aurora-l2.h b/arch/arm/mm/cache-aurora-l2.h deleted file mode 100644 index c86124769831..000000000000 --- a/arch/arm/mm/cache-aurora-l2.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * AURORA shared L2 cache controller support - * - * Copyright (C) 2012 Marvell - * - * Yehuda Yitschak - * Gregory CLEMENT - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __ASM_ARM_HARDWARE_AURORA_L2_H -#define __ASM_ARM_HARDWARE_AURORA_L2_H - -#define AURORA_SYNC_REG 0x700 -#define AURORA_RANGE_BASE_ADDR_REG 0x720 -#define AURORA_FLUSH_PHY_ADDR_REG 0x7f0 -#define AURORA_INVAL_RANGE_REG 0x774 -#define AURORA_CLEAN_RANGE_REG 0x7b4 -#define AURORA_FLUSH_RANGE_REG 0x7f4 - -#define AURORA_ACR_REPLACEMENT_OFFSET 27 -#define AURORA_ACR_REPLACEMENT_MASK \ - (0x3 << AURORA_ACR_REPLACEMENT_OFFSET) -#define AURORA_ACR_REPLACEMENT_TYPE_WAYRR \ - (0 << AURORA_ACR_REPLACEMENT_OFFSET) -#define AURORA_ACR_REPLACEMENT_TYPE_LFSR \ - (1 << AURORA_ACR_REPLACEMENT_OFFSET) -#define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \ - (3 << AURORA_ACR_REPLACEMENT_OFFSET) - -#define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET 0 -#define AURORA_ACR_FORCE_WRITE_POLICY_MASK \ - (0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) -#define AURORA_ACR_FORCE_WRITE_POLICY_DIS \ - (0 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) -#define AURORA_ACR_FORCE_WRITE_BACK_POLICY \ - (1 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) -#define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ - (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) - -#define MAX_RANGE_SIZE 1024 - -#define AURORA_WAY_SIZE_SHIFT 2 - -#define AURORA_CTRL_FW 0x100 - -/* chose a number outside L2X0_CACHE_ID_PART_MASK to be sure to make - * the distinction between a number coming from hardware and a number - * coming from the device tree */ -#define AURORA_CACHE_ID 0x100 - -#endif /* __ASM_ARM_HARDWARE_AURORA_L2_H */ diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 5b251c8ecd45..428d08718107 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -18,8 +18,8 @@ #include #include #include +#include #include "cache-tauros3.h" -#include "cache-aurora-l2.h" struct l2c_init_data { const char *type; -- cgit From 1a85cb4b0d2984a6d1afb03e2038855d654c9892 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Fri, 12 Jul 2019 05:46:51 +0100 Subject: ARM: 8887/1: aurora-l2: add prefix to MAX_RANGE_SIZE The macro name is too generic, so add a AURORA_ prefix. Signed-off-by: Jan Luebbe Reviewed-by: Gregory CLEMENT Signed-off-by: Chris Packham Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 428d08718107..83b733a1f1e6 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1352,8 +1352,8 @@ static unsigned long aurora_range_end(unsigned long start, unsigned long end) * since cache range operations stall the CPU pipeline * until completion. */ - if (end > start + MAX_RANGE_SIZE) - end = start + MAX_RANGE_SIZE; + if (end > start + AURORA_MAX_RANGE_SIZE) + end = start + AURORA_MAX_RANGE_SIZE; /* * Cache range operations can't straddle a page boundary. -- cgit From fd3bbde717b00a2db75d0c93264f412c1176008f Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 12 Jul 2019 05:46:53 +0100 Subject: ARM: 8886/1: l2x0: support parity-enable/disable on aurora The aurora cache on the Marvell Armada-XP SoC supports the same tag parity features as the other l2x0 cache implementations. [jlu@pengutronix.de: use aurora specific define AURORA_ACR_PARITY_EN] Signed-off-by: Chris Packham Signed-off-by: Jan Luebbe Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 83b733a1f1e6..46a616ec6b0c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1493,6 +1493,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "arm,parity-enable")) { + mask |= AURORA_ACR_PARITY_EN; + val |= AURORA_ACR_PARITY_EN; + } else if (of_property_read_bool(np, "arm,parity-disable")) { + mask |= AURORA_ACR_PARITY_EN; + } + *aux_val &= ~mask; *aux_val |= val; *aux_mask &= ~mask; -- cgit From c8abbd6f9dc47dffaea5adc7172ffa59a16401e3 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 12 Jul 2019 05:46:55 +0100 Subject: ARM: 8890/1: l2x0: add marvell,ecc-enable property for aurora The aurora cache on the Marvell Armada-XP SoC supports ECC protection for the L2 data arrays. Add a "marvell,ecc-enable" device tree property which can be used to enable this. [jlu@pengutronix.de: use aurora specific define AURORA_ACR_ECC_EN] Signed-off-by: Chris Packham Signed-off-by: Jan Luebbe Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 46a616ec6b0c..12c26eb88afb 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1493,6 +1493,11 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "marvell,ecc-enable")) { + mask |= AURORA_ACR_ECC_EN; + val |= AURORA_ACR_ECC_EN; + } + if (of_property_read_bool(np, "arm,parity-enable")) { mask |= AURORA_ACR_PARITY_EN; val |= AURORA_ACR_PARITY_EN; -- cgit From 00d2ec1e6bd82c0538e6dd3e4a4040de93ba4fef Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Fri, 30 Aug 2019 14:27:56 +0100 Subject: ARM: 8903/1: ensure that usable memory in bank 0 starts from a PMD-aligned address The calculation of memblock_limit in adjust_lowmem_bounds() assumes that bank 0 starts from a PMD-aligned address. However, the beginning of the first bank may be NOMAP memory and the start of usable memory will be not aligned to PMD boundary. In such case the memblock_limit will be set to the end of the NOMAP region, which will prevent any memblock allocations. Mark the region between the end of the NOMAP area and the next PMD-aligned address as NOMAP as well, so that the usable memory will start at PMD-aligned address. Signed-off-by: Mike Rapoport Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index d9a0038774a6..d5e0b908f0ba 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1177,6 +1177,22 @@ void __init adjust_lowmem_bounds(void) */ vmalloc_limit = (u64)(uintptr_t)vmalloc_min - PAGE_OFFSET + PHYS_OFFSET; + /* + * The first usable region must be PMD aligned. Mark its start + * as MEMBLOCK_NOMAP if it isn't + */ + for_each_memblock(memory, reg) { + if (!memblock_is_nomap(reg)) { + if (!IS_ALIGNED(reg->base, PMD_SIZE)) { + phys_addr_t len; + + len = round_up(reg->base, PMD_SIZE) - reg->base; + memblock_mark_nomap(reg->base, len); + } + break; + } + } + for_each_memblock(memory, reg) { phys_addr_t block_start = reg->base; phys_addr_t block_end = reg->base + reg->size; -- cgit From 1d31999cf04c21709f72ceb17e65b54a401330da Mon Sep 17 00:00:00 2001 From: Chester Lin Date: Fri, 30 Aug 2019 14:30:07 +0100 Subject: ARM: 8904/1: skip nomap memblocks while finding the lowmem/highmem boundary adjust_lowmem_bounds() checks every memblocks in order to find the boundary between lowmem and highmem. However some memblocks could be marked as NOMAP so they are not used by kernel, which should be skipped while calculating the boundary. Signed-off-by: Chester Lin Reviewed-by: Mike Rapoport Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index d5e0b908f0ba..25da9b2d9610 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1197,6 +1197,9 @@ void __init adjust_lowmem_bounds(void) phys_addr_t block_start = reg->base; phys_addr_t block_end = reg->base + reg->size; + if (memblock_is_nomap(reg)) + continue; + if (reg->base < vmalloc_limit) { if (block_end > lowmem_limit) /* -- cgit