[PATCH RESEND v1 4/4] powerpc/vdso: Add support for time namespaces

2021-03-31 Thread Christophe Leroy
This patch adds the necessary glue to provide time namespaces.

Things are mainly copied from ARM64.

__arch_get_timens_vdso_data() calculates timens vdso data position
based on the vdso data position, knowing it is the next page in vvar.
This avoids having to redo the mflr/bcl/mflr/mtlr dance to locate
the page relative to running code position.

Signed-off-by: Christophe Leroy 
---
 arch/powerpc/Kconfig |   3 +-
 arch/powerpc/include/asm/vdso/gettimeofday.h |  10 ++
 arch/powerpc/include/asm/vdso_datapage.h |   2 -
 arch/powerpc/kernel/vdso.c   | 116 ---
 arch/powerpc/kernel/vdso32/vdso32.lds.S  |   2 +-
 arch/powerpc/kernel/vdso64/vdso64.lds.S  |   2 +-
 6 files changed, 114 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c1344c05226c..71daff5f15d5 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -172,6 +172,7 @@ config PPC
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_VULNERABILITIES  if PPC_BARRIER_NOSPEC
select GENERIC_EARLY_IOREMAP
+   select GENERIC_GETTIMEOFDAY
select GENERIC_IRQ_SHOW
select GENERIC_IRQ_SHOW_LEVEL
select GENERIC_PCI_IOMAPif PCI
@@ -179,7 +180,7 @@ config PPC
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
-   select GENERIC_GETTIMEOFDAY
+   select GENERIC_VDSO_TIME_NS
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HUGE_VMAP  if PPC_BOOK3S_64 && 
PPC_RADIX_MMU
select HAVE_ARCH_JUMP_LABEL
diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h 
b/arch/powerpc/include/asm/vdso/gettimeofday.h
index d453e725c79f..e448df1dd071 100644
--- a/arch/powerpc/include/asm/vdso/gettimeofday.h
+++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
@@ -2,6 +2,8 @@
 #ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
 #define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
 
+#include 
+
 #ifdef __ASSEMBLY__
 
 #include 
@@ -153,6 +155,14 @@ static __always_inline u64 __arch_get_hw_counter(s32 
clock_mode,
 
 const struct vdso_data *__arch_get_vdso_data(void);
 
+#ifdef CONFIG_TIME_NS
+static __always_inline
+const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
+{
+   return (void *)vd + PAGE_SIZE;
+}
+#endif
+
 static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
 {
return true;
diff --git a/arch/powerpc/include/asm/vdso_datapage.h 
b/arch/powerpc/include/asm/vdso_datapage.h
index 3f958ecf2beb..a585c8e538ff 100644
--- a/arch/powerpc/include/asm/vdso_datapage.h
+++ b/arch/powerpc/include/asm/vdso_datapage.h
@@ -107,9 +107,7 @@ extern struct vdso_arch_data *vdso_data;
bcl 20, 31, .+4
 999:
mflr\ptr
-#if CONFIG_PPC_PAGE_SHIFT > 14
addis   \ptr, \ptr, (_vdso_datapage - 999b)@ha
-#endif
addi\ptr, \ptr, (_vdso_datapage - 999b)@l
 .endm
 
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index b14907209822..717f2c9a7573 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -50,6 +51,12 @@ static union {
 } vdso_data_store __page_aligned_data;
 struct vdso_arch_data *vdso_data = &vdso_data_store.data;
 
+enum vvar_pages {
+   VVAR_DATA_PAGE_OFFSET,
+   VVAR_TIMENS_PAGE_OFFSET,
+   VVAR_NR_PAGES,
+};
+
 static int vdso_mremap(const struct vm_special_mapping *sm, struct 
vm_area_struct *new_vma,
   unsigned long text_size)
 {
@@ -73,8 +80,12 @@ static int vdso64_mremap(const struct vm_special_mapping 
*sm, struct vm_area_str
return vdso_mremap(sm, new_vma, &vdso64_end - &vdso64_start);
 }
 
+static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
+struct vm_area_struct *vma, struct vm_fault *vmf);
+
 static struct vm_special_mapping vvar_spec __ro_after_init = {
.name = "[vvar]",
+   .fault = vvar_fault,
 };
 
 static struct vm_special_mapping vdso32_spec __ro_after_init = {
@@ -87,6 +98,94 @@ static struct vm_special_mapping vdso64_spec __ro_after_init 
= {
.mremap = vdso64_mremap,
 };
 
+#ifdef CONFIG_TIME_NS
+struct vdso_data *arch_get_vdso_data(void *vvar_page)
+{
+   return ((struct vdso_arch_data *)vvar_page)->data;
+}
+
+/*
+ * 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.
+ * Subsequent faults will map in data for the new namespace.
+ *
+ * For more details see timens_setup_vdso_data().
+ */
+int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
+{
+   struct mm_struct *mm = task->mm;
+   struct vm_area_struct *vma;
+
+   mmap_read_lock(mm);
+
+   for (vma = mm->mmap; vma; vma = vma->vm_next) {
+   unsigned long size = vma->vm_end - vma->vm_start;
+

Re: [PATCH RESEND v1 4/4] powerpc/vdso: Add support for time namespaces

2021-04-05 Thread Andrei Vagin
On Wed, Mar 31, 2021 at 04:48:47PM +, Christophe Leroy wrote:
> This patch adds the necessary glue to provide time namespaces.
> 
> Things are mainly copied from ARM64.
> 
> __arch_get_timens_vdso_data() calculates timens vdso data position
> based on the vdso data position, knowing it is the next page in vvar.
> This avoids having to redo the mflr/bcl/mflr/mtlr dance to locate
> the page relative to running code position.
>

Acked-by: Andrei Vagin 
 
> Signed-off-by: Christophe Leroy 


Re: [PATCH RESEND v1 4/4] powerpc/vdso: Add support for time namespaces

2021-04-12 Thread Vincenzo Frascino



On 3/31/21 5:48 PM, Christophe Leroy wrote:
> This patch adds the necessary glue to provide time namespaces.
> 
> Things are mainly copied from ARM64.
> 
> __arch_get_timens_vdso_data() calculates timens vdso data position
> based on the vdso data position, knowing it is the next page in vvar.
> This avoids having to redo the mflr/bcl/mflr/mtlr dance to locate
> the page relative to running code position.
> 
> Signed-off-by: Christophe Leroy 

Reviewed-by: Vincenzo Frascino  # vDSO parts

> ---
>  arch/powerpc/Kconfig |   3 +-
>  arch/powerpc/include/asm/vdso/gettimeofday.h |  10 ++
>  arch/powerpc/include/asm/vdso_datapage.h |   2 -
>  arch/powerpc/kernel/vdso.c   | 116 ---
>  arch/powerpc/kernel/vdso32/vdso32.lds.S  |   2 +-
>  arch/powerpc/kernel/vdso64/vdso64.lds.S  |   2 +-
>  6 files changed, 114 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index c1344c05226c..71daff5f15d5 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -172,6 +172,7 @@ config PPC
>   select GENERIC_CPU_AUTOPROBE
>   select GENERIC_CPU_VULNERABILITIES  if PPC_BARRIER_NOSPEC
>   select GENERIC_EARLY_IOREMAP
> + select GENERIC_GETTIMEOFDAY
>   select GENERIC_IRQ_SHOW
>   select GENERIC_IRQ_SHOW_LEVEL
>   select GENERIC_PCI_IOMAPif PCI
> @@ -179,7 +180,7 @@ config PPC
>   select GENERIC_STRNCPY_FROM_USER
>   select GENERIC_STRNLEN_USER
>   select GENERIC_TIME_VSYSCALL
> - select GENERIC_GETTIMEOFDAY
> + select GENERIC_VDSO_TIME_NS
>   select HAVE_ARCH_AUDITSYSCALL
>   select HAVE_ARCH_HUGE_VMAP  if PPC_BOOK3S_64 && 
> PPC_RADIX_MMU
>   select HAVE_ARCH_JUMP_LABEL
> diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h 
> b/arch/powerpc/include/asm/vdso/gettimeofday.h
> index d453e725c79f..e448df1dd071 100644
> --- a/arch/powerpc/include/asm/vdso/gettimeofday.h
> +++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
> @@ -2,6 +2,8 @@
>  #ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
>  #define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
>  
> +#include 
> +
>  #ifdef __ASSEMBLY__
>  
>  #include 
> @@ -153,6 +155,14 @@ static __always_inline u64 __arch_get_hw_counter(s32 
> clock_mode,
>  
>  const struct vdso_data *__arch_get_vdso_data(void);
>  
> +#ifdef CONFIG_TIME_NS
> +static __always_inline
> +const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data 
> *vd)
> +{
> + return (void *)vd + PAGE_SIZE;
> +}
> +#endif
> +
>  static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
>  {
>   return true;
> diff --git a/arch/powerpc/include/asm/vdso_datapage.h 
> b/arch/powerpc/include/asm/vdso_datapage.h
> index 3f958ecf2beb..a585c8e538ff 100644
> --- a/arch/powerpc/include/asm/vdso_datapage.h
> +++ b/arch/powerpc/include/asm/vdso_datapage.h
> @@ -107,9 +107,7 @@ extern struct vdso_arch_data *vdso_data;
>   bcl 20, 31, .+4
>  999:
>   mflr\ptr
> -#if CONFIG_PPC_PAGE_SHIFT > 14
>   addis   \ptr, \ptr, (_vdso_datapage - 999b)@ha
> -#endif
>   addi\ptr, \ptr, (_vdso_datapage - 999b)@l
>  .endm
>  
> diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
> index b14907209822..717f2c9a7573 100644
> --- a/arch/powerpc/kernel/vdso.c
> +++ b/arch/powerpc/kernel/vdso.c
> @@ -18,6 +18,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> @@ -50,6 +51,12 @@ static union {
>  } vdso_data_store __page_aligned_data;
>  struct vdso_arch_data *vdso_data = &vdso_data_store.data;
>  
> +enum vvar_pages {
> + VVAR_DATA_PAGE_OFFSET,
> + VVAR_TIMENS_PAGE_OFFSET,
> + VVAR_NR_PAGES,
> +};
> +
>  static int vdso_mremap(const struct vm_special_mapping *sm, struct 
> vm_area_struct *new_vma,
>  unsigned long text_size)
>  {
> @@ -73,8 +80,12 @@ static int vdso64_mremap(const struct vm_special_mapping 
> *sm, struct vm_area_str
>   return vdso_mremap(sm, new_vma, &vdso64_end - &vdso64_start);
>  }
>  
> +static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> +  struct vm_area_struct *vma, struct vm_fault *vmf);
> +
>  static struct vm_special_mapping vvar_spec __ro_after_init = {
>   .name = "[vvar]",
> + .fault = vvar_fault,
>  };
>  
>  static struct vm_special_mapping vdso32_spec __ro_after_init = {
> @@ -87,6 +98,94 @@ static struct vm_special_mapping vdso64_spec 
> __ro_after_init = {
>   .mremap = vdso64_mremap,
>  };
>  
> +#ifdef CONFIG_TIME_NS
> +struct vdso_data *arch_get_vdso_data(void *vvar_page)
> +{
> + return ((struct vdso_arch_data *)vvar_page)->data;
> +}
> +
> +/*
> + * 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.
> + * Subsequent faults will map in data for the new namespace.
> + *
> + * For more details see timens_setup_vdso_