summaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@mips.com>2018-08-30 11:01:21 -0700
committerPaul Burton <paul.burton@mips.com>2018-08-31 10:07:21 -0700
commit0f02cfbc3d9e413d450d8d0fd660077c23f67eff (patch)
tree37d29a9eef33764f7974c5863a9f7a7fcdac7d9b /arch/mips
parent5b394b2ddf0347bef56e50c69a58773c94343ff3 (diff)
downloadlinux-0f02cfbc3d9e413d450d8d0fd660077c23f67eff.tar.gz
linux-0f02cfbc3d9e413d450d8d0fd660077c23f67eff.tar.bz2
linux-0f02cfbc3d9e413d450d8d0fd660077c23f67eff.zip
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')
-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 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -20,6 +21,7 @@
#include <asm/abi.h>
#include <asm/mips-cps.h>
+#include <asm/page.h>
#include <asm/vdso.h>
/* Kernel-provided data used by the VDSO. */
@@ -128,12 +130,30 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
vvar_size = gic_size + PAGE_SIZE;
size = vvar_size + image->size;
+ /*
+ * Find a region that's large enough for us to perform the
+ * colour-matching alignment below.
+ */
+ if (cpu_has_dc_aliases)
+ size += shm_align_mask + 1;
+
base = get_unmapped_area(NULL, 0, size, 0, 0);
if (IS_ERR_VALUE(base)) {
ret = base;
goto out;
}
+ /*
+ * If we suffer from dcache aliasing, ensure that the VDSO data page
+ * mapping is coloured the same as the kernel's mapping of that memory.
+ * This ensures that when the kernel updates the VDSO data userland
+ * will observe it without requiring cache invalidations.
+ */
+ if (cpu_has_dc_aliases) {
+ base = __ALIGN_MASK(base, shm_align_mask);
+ base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask;
+ }
+
data_addr = base + gic_size;
vdso_addr = data_addr + PAGE_SIZE;