[LEDE-DEV] [PATCH] kernel: fix VDSO problem on MIPS

Hauke Mehrtens hauke at hauke-m.de
Thu Aug 10 15:14:27 PDT 2017


This fixes the VDSO problems on the Lantiq VR9 MIPS SoC.
The gettimeofday() sometimes returned old data because of a cache
aliasing problems on MIPS CPUs, to work around this problem VDSO
gettimeofday support was deactivated for MIPS in LEDE.
This problem made ping show very high times like a delay of 4289967.657
ms.

1.000.000 calls to clock_gettime(CLOCK_MONOTONIC, &tp); take 1 second
without VDSO support and 0.35 seconds with VDSO support on Lantiq VR9.

Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 ...MIPS-work-around-aliasing-issue-with-VDSO.patch | 63 ++++++++++++++++++++++
 .../pending-4.4/206-mips-disable-vdso.patch        | 21 --------
 ...MIPS-work-around-aliasing-issue-with-VDSO.patch | 63 ++++++++++++++++++++++
 .../pending-4.9/206-mips-disable-vdso.patch        | 28 ----------
 4 files changed, 126 insertions(+), 49 deletions(-)
 create mode 100644 target/linux/generic/pending-4.4/206-MIPS-work-around-aliasing-issue-with-VDSO.patch
 delete mode 100644 target/linux/generic/pending-4.4/206-mips-disable-vdso.patch
 create mode 100644 target/linux/generic/pending-4.9/206-MIPS-work-around-aliasing-issue-with-VDSO.patch
 delete mode 100644 target/linux/generic/pending-4.9/206-mips-disable-vdso.patch

diff --git a/target/linux/generic/pending-4.4/206-MIPS-work-around-aliasing-issue-with-VDSO.patch b/target/linux/generic/pending-4.4/206-MIPS-work-around-aliasing-issue-with-VDSO.patch
new file mode 100644
index 0000000000..b62557b7b5
--- /dev/null
+++ b/target/linux/generic/pending-4.4/206-MIPS-work-around-aliasing-issue-with-VDSO.patch
@@ -0,0 +1,63 @@
+From a5513a09cbb946e9d031fb65d6c2ac7c32c9042c Mon Sep 17 00:00:00 2001
+From: James Hogan <james.hogan at imgtec.com>
+Date: Thu, 10 Aug 2017 22:56:47 +0200
+Subject: MIPS: work around aliasing issue with VDSO
+
+I notice that the mips_vdso_data is updated by update_vsyscall() via
+kseg0, however userland will be accessing it via the mapping 1 page
+below the VDSO.
+
+If the kernel data happened to be placed such that the mips_vdso_data in
+kseg0 and the user mapping had different page colours then you could
+easily hit aliasing issues. A couple of well placed flushes or some more
+careful placement of the VDSO data might well fix it, as could some
+random patch changing the positioning of the data such that it
+coincidentally lined up on the same colour.
+
+The patch unfortunately hacks arch_get_unmapped_area_common so that it
+does the colour alignment on non-shared anonymous pages, as long as
+non-zero pgoff is provided. Hopefully no userland code would try
+mmap'ing anonymous memory with a file offset, and so it should be
+harmless.
+
+It doesn't look like we can just pass MAP_SHARED to avoid the hack as
+then pgoff will get cleared by get_unmapped_area()).
+---
+ arch/mips/kernel/vdso.c | 7 ++++++-
+ arch/mips/mm/mmap.c     | 2 +-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
+index f9dbfb14af33..9509b5122e70 100644
+--- a/arch/mips/kernel/vdso.c
++++ b/arch/mips/kernel/vdso.c
+@@ -129,7 +129,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+ 	vvar_size = gic_size + PAGE_SIZE;
+ 	size = vvar_size + image->size;
+ 
+-	base = get_unmapped_area(NULL, 0, size, 0, 0);
++	/*
++	 * Hack to get the user mapping of the VDSO data page matching the cache
++	 * colour of its kseg0 address.
++	 */
++	base = get_unmapped_area(NULL, 0, size,
++			(virt_to_phys(&vdso_data) - gic_size) >> PAGE_SHIFT, 0);
+ 	if (IS_ERR_VALUE(base)) {
+ 		ret = base;
+ 		goto out;
+diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
+index d08ea3ff0f53..cb468b0ea45c 100644
+--- a/arch/mips/mm/mmap.c
++++ b/arch/mips/mm/mmap.c
+@@ -80,7 +80,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
+ 	}
+ 
+ 	do_color_align = 0;
+-	if (filp || (flags & MAP_SHARED))
++	if (filp || (flags & MAP_SHARED) || pgoff)
+ 		do_color_align = 1;
+ 
+ 	/* requesting a specific address */
+-- 
+2.11.0
+
diff --git a/target/linux/generic/pending-4.4/206-mips-disable-vdso.patch b/target/linux/generic/pending-4.4/206-mips-disable-vdso.patch
deleted file mode 100644
index 51b1d041bf..0000000000
--- a/target/linux/generic/pending-4.4/206-mips-disable-vdso.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Disable MIPS VDSO until the cache issues have been sorted out.
-
-Signed-off-by: Felix Fietkau <nbd at nbd.name>
-
---- a/arch/mips/vdso/Makefile
-+++ b/arch/mips/vdso/Makefile
-@@ -28,11 +28,11 @@ aflags-vdso := $(ccflags-vdso) \
- # the comments on that file.
- #
- ifndef CONFIG_CPU_MIPSR6
--  ifeq ($(call ld-ifversion, -lt, 22500000, y),y)
--    $(warning MIPS VDSO requires binutils >= 2.25)
-+#  ifeq ($(call ld-ifversion, -lt, 22500000, y),y)
-+#    $(warning MIPS VDSO requires binutils >= 2.25)
-     obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
-     ccflags-vdso += -DDISABLE_MIPS_VDSO
--  endif
-+#  endif
- endif
- 
- # VDSO linker flags.
diff --git a/target/linux/generic/pending-4.9/206-MIPS-work-around-aliasing-issue-with-VDSO.patch b/target/linux/generic/pending-4.9/206-MIPS-work-around-aliasing-issue-with-VDSO.patch
new file mode 100644
index 0000000000..b62557b7b5
--- /dev/null
+++ b/target/linux/generic/pending-4.9/206-MIPS-work-around-aliasing-issue-with-VDSO.patch
@@ -0,0 +1,63 @@
+From a5513a09cbb946e9d031fb65d6c2ac7c32c9042c Mon Sep 17 00:00:00 2001
+From: James Hogan <james.hogan at imgtec.com>
+Date: Thu, 10 Aug 2017 22:56:47 +0200
+Subject: MIPS: work around aliasing issue with VDSO
+
+I notice that the mips_vdso_data is updated by update_vsyscall() via
+kseg0, however userland will be accessing it via the mapping 1 page
+below the VDSO.
+
+If the kernel data happened to be placed such that the mips_vdso_data in
+kseg0 and the user mapping had different page colours then you could
+easily hit aliasing issues. A couple of well placed flushes or some more
+careful placement of the VDSO data might well fix it, as could some
+random patch changing the positioning of the data such that it
+coincidentally lined up on the same colour.
+
+The patch unfortunately hacks arch_get_unmapped_area_common so that it
+does the colour alignment on non-shared anonymous pages, as long as
+non-zero pgoff is provided. Hopefully no userland code would try
+mmap'ing anonymous memory with a file offset, and so it should be
+harmless.
+
+It doesn't look like we can just pass MAP_SHARED to avoid the hack as
+then pgoff will get cleared by get_unmapped_area()).
+---
+ arch/mips/kernel/vdso.c | 7 ++++++-
+ arch/mips/mm/mmap.c     | 2 +-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
+index f9dbfb14af33..9509b5122e70 100644
+--- a/arch/mips/kernel/vdso.c
++++ b/arch/mips/kernel/vdso.c
+@@ -129,7 +129,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+ 	vvar_size = gic_size + PAGE_SIZE;
+ 	size = vvar_size + image->size;
+ 
+-	base = get_unmapped_area(NULL, 0, size, 0, 0);
++	/*
++	 * Hack to get the user mapping of the VDSO data page matching the cache
++	 * colour of its kseg0 address.
++	 */
++	base = get_unmapped_area(NULL, 0, size,
++			(virt_to_phys(&vdso_data) - gic_size) >> PAGE_SHIFT, 0);
+ 	if (IS_ERR_VALUE(base)) {
+ 		ret = base;
+ 		goto out;
+diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
+index d08ea3ff0f53..cb468b0ea45c 100644
+--- a/arch/mips/mm/mmap.c
++++ b/arch/mips/mm/mmap.c
+@@ -80,7 +80,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
+ 	}
+ 
+ 	do_color_align = 0;
+-	if (filp || (flags & MAP_SHARED))
++	if (filp || (flags & MAP_SHARED) || pgoff)
+ 		do_color_align = 1;
+ 
+ 	/* requesting a specific address */
+-- 
+2.11.0
+
diff --git a/target/linux/generic/pending-4.9/206-mips-disable-vdso.patch b/target/linux/generic/pending-4.9/206-mips-disable-vdso.patch
deleted file mode 100644
index 9785f932e7..0000000000
--- a/target/linux/generic/pending-4.9/206-mips-disable-vdso.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From: Felix Fietkau <nbd at nbd.name>
-Subject: kernel: disable MIPS VDSO by default until the cache issues have been resolved
-
-lede-commit: 1185e645a773c86aa88cf04d0e2911dc62eb43f5
-Signed-off-by: Felix Fietkau <nbd at nbd.name>
----
- arch/mips/vdso/Makefile | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
-index c3dc12a8b7d9..28f66e3bb2c3 100644
---- a/arch/mips/vdso/Makefile
-+++ b/arch/mips/vdso/Makefile
-@@ -28,9 +28,9 @@ aflags-vdso := $(ccflags-vdso) \
- ifndef CONFIG_CPU_MIPSR6
-   ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
-     $(warning MIPS VDSO requires binutils >= 2.25)
--    obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
--    ccflags-vdso += -DDISABLE_MIPS_VDSO
-   endif
-+  obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
-+  ccflags-vdso += -DDISABLE_MIPS_VDSO
- endif
- 
- # VDSO linker flags.
--- 
-2.11.0
-
-- 
2.11.0




More information about the Lede-dev mailing list