aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@mips.com>2018-08-30 14:01:21 -0400
committerPaul Burton <paul.burton@mips.com>2018-08-31 13:07:21 -0400
commit0f02cfbc3d9e413d450d8d0fd660077c23f67eff (patch)
tree37d29a9eef33764f7974c5863a9f7a7fcdac7d9b /arch/mips/kernel
parent5b394b2ddf0347bef56e50c69a58773c94343ff3 (diff)
MIPS: VDSO: Match data page cache colouring when D$ aliases
When a system suffers from dcache aliasing a user program may observe stale VDSO data from an aliased cache line. Notably this can break the expectation that clock_gettime(CLOCK_MONOTONIC, ...) is, as its name suggests, monotonic. In order to ensure that users observe updates to the VDSO data page as intended, align the user mappings of the VDSO data page such that their cache colouring matches that of the virtual address range which the kernel will use to update the data page - typically its unmapped address within kseg0. This ensures that we don't introduce aliasing cache lines for the VDSO data page, and therefore that userland will observe updates without requiring cache invalidation. Signed-off-by: Paul Burton <paul.burton@mips.com> Reported-by: Hauke Mehrtens <hauke@hauke-m.de> Reported-by: Rene Nielsen <rene.nielsen@microsemi.com> Reported-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Fixes: ebb5e78cc634 ("MIPS: Initial implementation of a VDSO") Patchwork: https://patchwork.linux-mips.org/patch/20344/ Tested-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Tested-by: Hauke Mehrtens <hauke@hauke-m.de> Cc: James Hogan <jhogan@kernel.org> Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org # v4.4+
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/vdso.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 019035d7225c..8f845f6e5f42 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -13,6 +13,7 @@
13#include <linux/err.h> 13#include <linux/err.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/ioport.h> 15#include <linux/ioport.h>
16#include <linux/kernel.h>
16#include <linux/mm.h> 17#include <linux/mm.h>
17#include <linux/sched.h> 18#include <linux/sched.h>
18#include <linux/slab.h> 19#include <linux/slab.h>
@@ -20,6 +21,7 @@
20 21
21#include <asm/abi.h> 22#include <asm/abi.h>
22#include <asm/mips-cps.h> 23#include <asm/mips-cps.h>
24#include <asm/page.h>
23#include <asm/vdso.h> 25#include <asm/vdso.h>
24 26
25/* Kernel-provided data used by the VDSO. */ 27/* Kernel-provided data used by the VDSO. */
@@ -128,12 +130,30 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
128 vvar_size = gic_size + PAGE_SIZE; 130 vvar_size = gic_size + PAGE_SIZE;
129 size = vvar_size + image->size; 131 size = vvar_size + image->size;
130 132
133 /*
134 * Find a region that's large enough for us to perform the
135 * colour-matching alignment below.
136 */
137 if (cpu_has_dc_aliases)
138 size += shm_align_mask + 1;
139
131 base = get_unmapped_area(NULL, 0, size, 0, 0); 140 base = get_unmapped_area(NULL, 0, size, 0, 0);
132 if (IS_ERR_VALUE(base)) { 141 if (IS_ERR_VALUE(base)) {
133 ret = base; 142 ret = base;
134 goto out; 143 goto out;
135 } 144 }
136 145
146 /*
147 * If we suffer from dcache aliasing, ensure that the VDSO data page
148 * mapping is coloured the same as the kernel's mapping of that memory.
149 * This ensures that when the kernel updates the VDSO data userland
150 * will observe it without requiring cache invalidations.
151 */
152 if (cpu_has_dc_aliases) {
153 base = __ALIGN_MASK(base, shm_align_mask);
154 base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask;
155 }
156
137 data_addr = base + gic_size; 157 data_addr = base + gic_size;
138 vdso_addr = data_addr + PAGE_SIZE; 158 vdso_addr = data_addr + PAGE_SIZE;
139 159