On Mon, Jul 29, 2019 at 2:58 PM Dmitry Safonov <dima@xxxxxxxxxx> wrote: > > From: Andrei Vagin <avagin@xxxxxxxxxx> > > As modern applications fetch time from VDSO without entering the kernel, > it's needed to provide offsets for userspace code inside time namespace. > > A page for timens offsets is allocated on time namespace construction. > Put that page into VVAR for tasks inside timens and zero page for > host processes. > > As VDSO code is already optimized as much as possible in terms of speed, > any new if-condition in VDSO code is undesirable; the goal is to provide > two .so(s), as was originally suggested by Andy and Thomas: > - for host tasks with optimized-out clk_to_ns() without any penalty > - for processes inside timens with clk_to_ns() > For this purpose, define clk_to_ns() under CONFIG_TIME_NS. > > To eliminate any performance regression, clk_to_ns() will be called > under static_branch with follow-up patches, that adds support for > patching vdso. > > VDSO mappings are platform-specific, add Kconfig dependency for arch. > > Signed-off-by: Andrei Vagin <avagin@xxxxxxxxx> > Co-developed-by: Dmitry Safonov <dima@xxxxxxxxxx> > Signed-off-by: Dmitry Safonov <dima@xxxxxxxxxx> > --- > arch/Kconfig | 5 +++ > arch/x86/Kconfig | 1 + > arch/x86/entry/vdso/vdso-layout.lds.S | 9 ++++- > arch/x86/entry/vdso/vdso2c.c | 3 ++ > arch/x86/entry/vdso/vma.c | 12 +++++++ > arch/x86/include/asm/vdso.h | 1 + > init/Kconfig | 1 + > lib/vdso/gettimeofday.c | 47 +++++++++++++++++++++++++++ > 8 files changed, 78 insertions(+), 1 deletion(-) > > diff --git a/arch/Kconfig b/arch/Kconfig > index a7b57dd42c26..e43d27f510ec 100644 > --- a/arch/Kconfig > +++ b/arch/Kconfig > @@ -729,6 +729,11 @@ config HAVE_ARCH_NVRAM_OPS > config ISA_BUS_API > def_bool ISA > > +config ARCH_HAS_VDSO_TIME_NS > + bool > + help > + VDSO can add time-ns offsets without entering kernel. > + > # > # ABI hall of shame > # > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index 222855cc0158..91615938b470 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -81,6 +81,7 @@ config X86 > select ARCH_HAS_STRICT_MODULE_RWX > select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE > select ARCH_HAS_UBSAN_SANITIZE_ALL > + select ARCH_HAS_VDSO_TIME_NS > select ARCH_HAVE_NMI_SAFE_CMPXCHG > select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI > select ARCH_MIGHT_HAVE_PC_PARPORT > diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S > index 93c6dc7812d0..ba216527e59f 100644 > --- a/arch/x86/entry/vdso/vdso-layout.lds.S > +++ b/arch/x86/entry/vdso/vdso-layout.lds.S > @@ -7,6 +7,12 @@ > * This script controls its layout. > */ > > +#ifdef CONFIG_TIME_NS > +# define TIMENS_SZ PAGE_SIZE > +#else > +# define TIMENS_SZ 0 > +#endif > + > SECTIONS > { > /* > @@ -16,7 +22,7 @@ SECTIONS > * segment. > */ > > - vvar_start = . - 3 * PAGE_SIZE; > + vvar_start = . - (3 * PAGE_SIZE + TIMENS_SZ); > vvar_page = vvar_start; > > /* Place all vvars at the offsets in asm/vvar.h. */ > @@ -28,6 +34,7 @@ SECTIONS > > pvclock_page = vvar_start + PAGE_SIZE; > hvclock_page = vvar_start + 2 * PAGE_SIZE; > + timens_page = vvar_start + 3 * PAGE_SIZE; > > . = SIZEOF_HEADERS; > > diff --git a/arch/x86/entry/vdso/vdso2c.c b/arch/x86/entry/vdso/vdso2c.c > index ce67370d14e5..7380908045c7 100644 > --- a/arch/x86/entry/vdso/vdso2c.c > +++ b/arch/x86/entry/vdso/vdso2c.c > @@ -75,12 +75,14 @@ enum { > sym_vvar_page, > sym_pvclock_page, > sym_hvclock_page, > + sym_timens_page, > }; > > const int special_pages[] = { > sym_vvar_page, > sym_pvclock_page, > sym_hvclock_page, > + sym_timens_page, > }; > > struct vdso_sym { > @@ -93,6 +95,7 @@ struct vdso_sym required_syms[] = { > [sym_vvar_page] = {"vvar_page", true}, > [sym_pvclock_page] = {"pvclock_page", true}, > [sym_hvclock_page] = {"hvclock_page", true}, > + [sym_timens_page] = {"timens_page", true}, > {"VDSO32_NOTE_MASK", true}, > {"__kernel_vsyscall", true}, > {"__kernel_sigreturn", true}, > diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c > index 2dc4f0b5481c..9bd66f84db5e 100644 > --- a/arch/x86/entry/vdso/vma.c > +++ b/arch/x86/entry/vdso/vma.c > @@ -14,6 +14,7 @@ > #include <linux/elf.h> > #include <linux/cpu.h> > #include <linux/ptrace.h> > +#include <linux/time_namespace.h> > #include <asm/pvclock.h> > #include <asm/vgtod.h> > #include <asm/proto.h> > @@ -23,6 +24,7 @@ > #include <asm/desc.h> > #include <asm/cpufeature.h> > #include <clocksource/hyperv_timer.h> > +#include <asm/page.h> > > #if defined(CONFIG_X86_64) > unsigned int __read_mostly vdso64_enabled = 1; > @@ -135,6 +137,16 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, > if (tsc_pg && vclock_was_used(VCLOCK_HVCLOCK)) > return vmf_insert_pfn(vma, vmf->address, > vmalloc_to_pfn(tsc_pg)); > + } else if (sym_offset == image->sym_timens_page) { > + struct time_namespace *ns = current->nsproxy->time_ns; What, if anything, guarantees that all tasks in the mm share the same timens? --Andy