[PATCH RESEND v1 4/4] powerpc/vdso: Add support for time namespaces
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
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
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_