[PATCH 3/6] arm64/vdso: Add time namespace page

2020-06-24 Thread Andrei Vagin
Allocate the time namespace page among VVAR pages.  Provide
__arch_get_timens_vdso_data() helper for VDSO code to get the
code-relative position of VVARs on that special page.

If a task belongs to a time namespace then the VVAR page which contains
the system wide VDSO data is replaced with a namespace specific page
which has the same layout as the VVAR page. That page has vdso_data->seq
set to 1 to enforce the slow path and vdso_data->clock_mode set to
VCLOCK_TIMENS to enforce the time namespace handling path.

The extra check in the case that vdso_data->seq is odd, e.g. a concurrent
update of the VDSO data is in progress, is not really affecting regular
tasks which are not part of a time namespace as the task is spin waiting
for the update to finish and vdso_data->seq to become even again.

If a time namespace task hits that code path, it invokes the corresponding
time getter function which retrieves the real VVAR page, reads host time
and then adds the offset for the requested clock which is stored in the
special VVAR page.

The time-namespace page isn't allocated on !CONFIG_TIME_NAMESPACE, but
vma is the same size, which simplifies criu/vdso migration between
different kernel configs.

Cc: Mark Rutland 
Reviewed-by: Vincenzo Frascino 
Reviewed-by: Dmitry Safonov 
Signed-off-by: Andrei Vagin 
---
 arch/arm64/include/asm/vdso.h |  2 ++
 .../include/asm/vdso/compat_gettimeofday.h| 12 
 arch/arm64/include/asm/vdso/gettimeofday.h|  8 
 arch/arm64/kernel/vdso.c  | 19 ---
 arch/arm64/kernel/vdso/vdso.lds.S |  5 -
 arch/arm64/kernel/vdso32/vdso.lds.S   |  5 -
 include/vdso/datapage.h   |  1 +
 7 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 07468428fd29..f99dcb94b438 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -12,6 +12,8 @@
  */
 #define VDSO_LBASE 0x0
 
+#define __VVAR_PAGES2
+
 #ifndef __ASSEMBLY__
 
 #include 
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h 
b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index b6907ae78e53..b7c549d46d18 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -152,6 +152,18 @@ static __always_inline const struct vdso_data 
*__arch_get_vdso_data(void)
return ret;
 }
 
+#ifdef CONFIG_TIME_NS
+static __always_inline const struct vdso_data 
*__arch_get_timens_vdso_data(void)
+{
+   const struct vdso_data *ret;
+
+   /* See __arch_get_vdso_data(). */
+   asm volatile("mov %0, %1" : "=r"(ret) : "r"(_timens_data));
+
+   return ret;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/arm64/include/asm/vdso/gettimeofday.h 
b/arch/arm64/include/asm/vdso/gettimeofday.h
index afba6ba332f8..cf39eae5eaaf 100644
--- a/arch/arm64/include/asm/vdso/gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/gettimeofday.h
@@ -96,6 +96,14 @@ const struct vdso_data *__arch_get_vdso_data(void)
return _vdso_data;
 }
 
+#ifdef CONFIG_TIME_NS
+static __always_inline
+const struct vdso_data *__arch_get_timens_vdso_data(void)
+{
+   return _timens_data;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index bdf492a17dff..18854e6c1373 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -40,6 +40,12 @@ enum vdso_abi {
 #endif /* CONFIG_COMPAT_VDSO */
 };
 
+enum vvar_pages {
+   VVAR_DATA_PAGE_OFFSET,
+   VVAR_TIMENS_PAGE_OFFSET,
+   VVAR_NR_PAGES,
+};
+
 struct vdso_abi_info {
const char *name;
const char *vdso_code_start;
@@ -125,6 +131,11 @@ static int __vdso_init(enum vdso_abi abi)
 }
 
 #ifdef CONFIG_TIME_NS
+struct vdso_data *arch_get_vdso_data(void *vvar_page)
+{
+   return (struct vdso_data *)(vvar_page);
+}
+
 /*
  * The vvar mapping contains data for a specific time namespace, so when a task
  * changes namespace we must unmap its vvar data for the old namespace.
@@ -173,9 +184,11 @@ static int __setup_additional_pages(enum vdso_abi abi,
unsigned long gp_flags = 0;
void *ret;
 
+   BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);
+
vdso_text_len = vdso_info[abi].vdso_pages << PAGE_SHIFT;
/* Be sure to map the data page */
-   vdso_mapping_len = vdso_text_len + PAGE_SIZE;
+   vdso_mapping_len = vdso_text_len + VVAR_NR_PAGES * PAGE_SIZE;
 
vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
if (IS_ERR_VALUE(vdso_base)) {
@@ -183,7 +196,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
goto up_fail;
}
 
-   ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
+   ret = _install_special_mapping(mm, vdso_base, VVAR_NR_PAGES 

[PATCH 3/6] arm64/vdso: Add time namespace page

2020-06-16 Thread Andrei Vagin
Allocate the time namespace page among VVAR pages.  Provide
__arch_get_timens_vdso_data() helper for VDSO code to get the
code-relative position of VVARs on that special page.

If a task belongs to a time namespace then the VVAR page which contains
the system wide VDSO data is replaced with a namespace specific page
which has the same layout as the VVAR page. That page has vdso_data->seq
set to 1 to enforce the slow path and vdso_data->clock_mode set to
VCLOCK_TIMENS to enforce the time namespace handling path.

The extra check in the case that vdso_data->seq is odd, e.g. a concurrent
update of the VDSO data is in progress, is not really affecting regular
tasks which are not part of a time namespace as the task is spin waiting
for the update to finish and vdso_data->seq to become even again.

If a time namespace task hits that code path, it invokes the corresponding
time getter function which retrieves the real VVAR page, reads host time
and then adds the offset for the requested clock which is stored in the
special VVAR page.

Cc: Mark Rutland 
Reviewed-by: Vincenzo Frascino 
Reviewed-by: Dmitry Safonov 
Signed-off-by: Andrei Vagin 
---
 arch/arm64/include/asm/vdso.h |  2 ++
 .../include/asm/vdso/compat_gettimeofday.h| 12 
 arch/arm64/include/asm/vdso/gettimeofday.h|  8 
 arch/arm64/kernel/vdso.c  | 19 ---
 arch/arm64/kernel/vdso/vdso.lds.S |  5 -
 arch/arm64/kernel/vdso32/vdso.lds.S   |  5 -
 include/vdso/datapage.h   |  1 +
 7 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 07468428fd29..f99dcb94b438 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -12,6 +12,8 @@
  */
 #define VDSO_LBASE 0x0
 
+#define __VVAR_PAGES2
+
 #ifndef __ASSEMBLY__
 
 #include 
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h 
b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index b6907ae78e53..b7c549d46d18 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -152,6 +152,18 @@ static __always_inline const struct vdso_data 
*__arch_get_vdso_data(void)
return ret;
 }
 
+#ifdef CONFIG_TIME_NS
+static __always_inline const struct vdso_data 
*__arch_get_timens_vdso_data(void)
+{
+   const struct vdso_data *ret;
+
+   /* See __arch_get_vdso_data(). */
+   asm volatile("mov %0, %1" : "=r"(ret) : "r"(_timens_data));
+
+   return ret;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/arm64/include/asm/vdso/gettimeofday.h 
b/arch/arm64/include/asm/vdso/gettimeofday.h
index afba6ba332f8..cf39eae5eaaf 100644
--- a/arch/arm64/include/asm/vdso/gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/gettimeofday.h
@@ -96,6 +96,14 @@ const struct vdso_data *__arch_get_vdso_data(void)
return _vdso_data;
 }
 
+#ifdef CONFIG_TIME_NS
+static __always_inline
+const struct vdso_data *__arch_get_timens_vdso_data(void)
+{
+   return _timens_data;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index df4bb736d28a..14d5b7642b62 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -40,6 +40,12 @@ enum vdso_abi {
 #endif /* CONFIG_COMPAT_VDSO */
 };
 
+enum vvar_pages {
+   VVAR_DATA_PAGE_OFFSET,
+   VVAR_TIMENS_PAGE_OFFSET,
+   VVAR_NR_PAGES,
+};
+
 struct vdso_abi_info {
const char *name;
const char *vdso_code_start;
@@ -126,6 +132,11 @@ static int __vdso_init(enum vdso_abi abi)
 }
 
 #ifdef CONFIG_TIME_NS
+struct vdso_data *arch_get_vdso_data(void *vvar_page)
+{
+   return (struct vdso_data *)(vvar_page);
+}
+
 /*
  * The vvar page layout depends on whether a task belongs to the root or
  * non-root time namespace. Whenever a task changes its namespace, the VVAR
@@ -175,9 +186,11 @@ static int __setup_additional_pages(enum vdso_abi abi,
unsigned long gp_flags = 0;
void *ret;
 
+   BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);
+
vdso_text_len = vdso_info[abi].vdso_pages << PAGE_SHIFT;
/* Be sure to map the data page */
-   vdso_mapping_len = vdso_text_len + PAGE_SIZE;
+   vdso_mapping_len = vdso_text_len + VVAR_NR_PAGES * PAGE_SIZE;
 
vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
if (IS_ERR_VALUE(vdso_base)) {
@@ -185,7 +198,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
goto up_fail;
}
 
-   ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
+   ret = _install_special_mapping(mm, vdso_base, VVAR_NR_PAGES * PAGE_SIZE,
   VM_READ|VM_MAYREAD|VM_PFNMAP,
   vdso_info[abi].dm);
if (IS_ERR(ret))
@@ 

Re: [PATCH 3/6] arm64/vdso: Add time namespace page

2020-06-03 Thread kbuild test robot
Hi Andrei,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on soc/for-next]
[also build test WARNING on arm/for-next xlnx/master kvmarm/next v5.7]
[cannot apply to arm64/for-next/core next-20200602]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:
https://github.com/0day-ci/linux/commits/Andrei-Vagin/arm64-add-the-time-namespace-support/20200603-020504
base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
config: arm64-allnoconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot 

All warnings (new ones prefixed by >>, old ones prefixed by <<):

>> arch/arm64/kernel/vdso.c:93:19: warning: no previous prototype for 
>> 'arch_get_vdso_data' [-Wmissing-prototypes]
93 | struct vdso_data *arch_get_vdso_data(void *vvar_page)
|   ^~

vim +/arch_get_vdso_data +93 arch/arm64/kernel/vdso.c

91  
92  
  > 93  struct vdso_data *arch_get_vdso_data(void *vvar_page)
94  {
95  return (struct vdso_data *)(vvar_page);
96  }
97  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip


Re: [PATCH 3/6] arm64/vdso: Add time namespace page

2020-06-02 Thread kbuild test robot
Hi Andrei,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on soc/for-next]
[also build test WARNING on arm/for-next kvmarm/next v5.7]
[cannot apply to arm64/for-next/core next-20200602]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:
https://github.com/0day-ci/linux/commits/Andrei-Vagin/arm64-add-the-time-namespace-support/20200603-020504
base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
config: arm64-randconfig-r004-20200602 (attached as .config)
compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 
2388a096e7865c043e83ece4e26654bd3d1a20d5)
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm64 cross compiling tool for clang build
# apt-get install binutils-aarch64-linux-gnu
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot 

All warnings (new ones prefixed by >>, old ones prefixed by <<):

>> arch/arm64/kernel/vdso.c:93:19: warning: no previous prototype for function 
>> 'arch_get_vdso_data' [-Wmissing-prototypes]
struct vdso_data *arch_get_vdso_data(void *vvar_page)
^
arch/arm64/kernel/vdso.c:93:1: note: declare 'static' if the function is not 
intended to be used outside of this translation unit
struct vdso_data *arch_get_vdso_data(void *vvar_page)
^
static
1 warning generated.

vim +/arch_get_vdso_data +93 arch/arm64/kernel/vdso.c

91  
92  
  > 93  struct vdso_data *arch_get_vdso_data(void *vvar_page)
94  {
95  return (struct vdso_data *)(vvar_page);
96  }
97  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip


Re: [PATCH 3/6] arm64/vdso: Add time namespace page

2020-06-02 Thread Dmitry Safonov
Hi Andrei,

On 6/2/20 7:02 PM, Andrei Vagin wrote:
[..]
> --- a/arch/arm64/include/asm/vdso.h
> +++ b/arch/arm64/include/asm/vdso.h
> @@ -12,6 +12,12 @@
>   */
>  #define VDSO_LBASE   0x0
>  
> +#ifdef CONFIG_TIME_NS
> +#define __VVAR_PAGES2
> +#else
> +#define __VVAR_PAGES1
> +#endif
> +
>  #ifndef __ASSEMBLY__

Not an issue as-is, but:

on x86 vdso+vvar is always the same size with/without CONFIG_TIME_NAMESPACE.

Timens page isn't allocated on !CONFIG_TIME_NAMESPACE, but vma is the
same size. Which simplifies criu/vdso migration between different kernel
configs.

Not any critical, but just to note..

Thanks,
  Dima


[PATCH 3/6] arm64/vdso: Add time namespace page

2020-06-02 Thread Andrei Vagin
Allocate the time namespace page among VVAR pages.  Provide
__arch_get_timens_vdso_data() helper for VDSO code to get the
code-relative position of VVARs on that special page.

If a task belongs to a time namespace then the VVAR page which contains
the system wide VDSO data is replaced with a namespace specific page
which has the same layout as the VVAR page. That page has vdso_data->seq
set to 1 to enforce the slow path and vdso_data->clock_mode set to
VCLOCK_TIMENS to enforce the time namespace handling path.

The extra check in the case that vdso_data->seq is odd, e.g. a concurrent
update of the VDSO data is in progress, is not really affecting regular
tasks which are not part of a time namespace as the task is spin waiting
for the update to finish and vdso_data->seq to become even again.

If a time namespace task hits that code path, it invokes the corresponding
time getter function which retrieves the real VVAR page, reads host time
and then adds the offset for the requested clock which is stored in the
special VVAR page.

Cc: Mark Rutland 
Reviewed-by: Vincenzo Frascino 
Signed-off-by: Andrei Vagin 
---
 arch/arm64/include/asm/vdso.h |  6 +
 .../include/asm/vdso/compat_gettimeofday.h| 12 ++
 arch/arm64/include/asm/vdso/gettimeofday.h|  8 +++
 arch/arm64/kernel/vdso.c  | 22 ---
 arch/arm64/kernel/vdso/vdso.lds.S |  5 -
 arch/arm64/kernel/vdso32/vdso.lds.S   |  5 -
 include/vdso/datapage.h   |  1 +
 7 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 07468428fd29..351c145d3808 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -12,6 +12,12 @@
  */
 #define VDSO_LBASE 0x0
 
+#ifdef CONFIG_TIME_NS
+#define __VVAR_PAGES2
+#else
+#define __VVAR_PAGES1
+#endif
+
 #ifndef __ASSEMBLY__
 
 #include 
diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h 
b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index b6907ae78e53..b7c549d46d18 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -152,6 +152,18 @@ static __always_inline const struct vdso_data 
*__arch_get_vdso_data(void)
return ret;
 }
 
+#ifdef CONFIG_TIME_NS
+static __always_inline const struct vdso_data 
*__arch_get_timens_vdso_data(void)
+{
+   const struct vdso_data *ret;
+
+   /* See __arch_get_vdso_data(). */
+   asm volatile("mov %0, %1" : "=r"(ret) : "r"(_timens_data));
+
+   return ret;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/arm64/include/asm/vdso/gettimeofday.h 
b/arch/arm64/include/asm/vdso/gettimeofday.h
index afba6ba332f8..cf39eae5eaaf 100644
--- a/arch/arm64/include/asm/vdso/gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/gettimeofday.h
@@ -96,6 +96,14 @@ const struct vdso_data *__arch_get_vdso_data(void)
return _vdso_data;
 }
 
+#ifdef CONFIG_TIME_NS
+static __always_inline
+const struct vdso_data *__arch_get_timens_vdso_data(void)
+{
+   return _timens_data;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 33df3cdf7982..1fa6f9362e56 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -46,6 +46,14 @@ enum arch_vdso_type {
 #define VDSO_TYPES (ARM64_VDSO + 1)
 #endif /* CONFIG_COMPAT_VDSO */
 
+enum vvar_pages {
+   VVAR_DATA_PAGE_OFFSET,
+#ifdef CONFIG_TIME_NS
+   VVAR_TIMENS_PAGE_OFFSET,
+#endif /* CONFIG_TIME_NS */
+   VVAR_NR_PAGES,
+};
+
 struct __vdso_abi {
const char *name;
const char *vdso_code_start;
@@ -81,6 +89,12 @@ static union {
 } vdso_data_store __page_aligned_data;
 struct vdso_data *vdso_data = vdso_data_store.data;
 
+
+struct vdso_data *arch_get_vdso_data(void *vvar_page)
+{
+   return (struct vdso_data *)(vvar_page);
+}
+
 static int __vdso_remap(enum arch_vdso_type arch_index,
const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
@@ -180,9 +194,11 @@ static int __setup_additional_pages(enum arch_vdso_type 
arch_index,
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
 
+   BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);
+
vdso_text_len = vdso_lookup[arch_index].vdso_pages << PAGE_SHIFT;
/* Be sure to map the data page */
-   vdso_mapping_len = vdso_text_len + PAGE_SIZE;
+   vdso_mapping_len = vdso_text_len + VVAR_NR_PAGES * PAGE_SIZE;
 
vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
if (IS_ERR_VALUE(vdso_base)) {
@@ -190,13 +206,13 @@ static int __setup_additional_pages(enum arch_vdso_type 
arch_index,
goto up_fail;
}
 
-   ret =