Commit aa5e65dc authored by Tiezhu Yang's avatar Tiezhu Yang Committed by Huacai Chen
Browse files

LoongArch: Add support to clone a time namespace



We can see that "Time namespaces are not supported" on LoongArch:

(1) clone3 test
  # cd tools/testing/selftests/clone3 && make && ./clone3
  ...
  # Time namespaces are not supported
  ok 18 # SKIP Skipping clone3() with CLONE_NEWTIME
  # Totals: pass:17 fail:0 xfail:0 xpass:0 skip:1 error:0

(2) timens test
  # cd tools/testing/selftests/timens && make && ./timens
  ...
  1..0 # SKIP Time namespaces are not supported

On LoongArch the current kernel does not support CONFIG_TIME_NS which
depends on GENERIC_VDSO_TIME_NS, select GENERIC_VDSO_TIME_NS to enable
CONFIG_TIME_NS to build kernel/time/namespace.c.

Additionally, it needs to define some arch-dependent functions for the
timens, such as __arch_get_timens_vdso_data(), arch_get_vdso_data() and
vdso_join_timens().

At the same time, modify the layout of vvar to use one page size for
generic vdso data, expand another page size for timens vdso data and
assign LOONGARCH_VDSO_DATA_SIZE (maybe exceeds a page size if expand in
the future) for loongarch vdso data, at last add the callback function
vvar_fault() and modify stack_top().

With this patch under CONFIG_TIME_NS:

(1) clone3 test
  # cd tools/testing/selftests/clone3 && make && ./clone3
  ...
  ok 18 [739] Result (0) matches expectation (0)
  # Totals: pass:18 fail:0 xfail:0 xpass:0 skip:0 error:0

(2) timens test
  # cd tools/testing/selftests/timens && make && ./timens
  ...
  # Totals: pass:10 fail:0 xfail:0 xpass:0 skip:0 error:0

Signed-off-by: default avatarTiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 65eea6b4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ config LOONGARCH
	select GENERIC_SCHED_CLOCK
	select GENERIC_SMP_IDLE_THREAD
	select GENERIC_TIME_VSYSCALL
	select GENERIC_VDSO_TIME_NS
	select GPIOLIB
	select HAS_IOPORT
	select HAVE_ARCH_AUDITSYSCALL
+1 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))

#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
#define sym_to_pfn(x)		__phys_to_pfn(__pa_symbol(x))

#define virt_to_pfn(kaddr)	PFN_DOWN(PHYSADDR(kaddr))
#define virt_to_page(kaddr)	pfn_to_page(virt_to_pfn(kaddr))
+8 −1
Original line number Diff line number Diff line
@@ -91,9 +91,16 @@ static inline bool loongarch_vdso_hres_capable(void)

static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
	return get_vdso_data();
	return (const struct vdso_data *)get_vdso_data();
}

#ifdef CONFIG_TIME_NS
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{
	return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE);
}
#endif
#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
+27 −5
Original line number Diff line number Diff line
@@ -16,10 +16,33 @@ struct vdso_pcpu_data {

struct loongarch_vdso_data {
	struct vdso_pcpu_data pdata[NR_CPUS];
	struct vdso_data data[CS_BASES]; /* Arch-independent data */
};

#define VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data))
/*
 * The layout of vvar:
 *
 *                      high
 * +---------------------+--------------------------+
 * | loongarch vdso data | LOONGARCH_VDSO_DATA_SIZE |
 * +---------------------+--------------------------+
 * |  time-ns vdso data  |        PAGE_SIZE         |
 * +---------------------+--------------------------+
 * |  generic vdso data  |        PAGE_SIZE         |
 * +---------------------+--------------------------+
 *                      low
 */
#define LOONGARCH_VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data))
#define LOONGARCH_VDSO_DATA_PAGES (LOONGARCH_VDSO_DATA_SIZE >> PAGE_SHIFT)

enum vvar_pages {
	VVAR_GENERIC_PAGE_OFFSET,
	VVAR_TIMENS_PAGE_OFFSET,
	VVAR_LOONGARCH_PAGES_START,
	VVAR_LOONGARCH_PAGES_END = VVAR_LOONGARCH_PAGES_START + LOONGARCH_VDSO_DATA_PAGES - 1,
	VVAR_NR_PAGES,
};

#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)

static inline unsigned long get_vdso_base(void)
{
@@ -34,10 +57,9 @@ static inline unsigned long get_vdso_base(void)
	return addr;
}

static inline const struct vdso_data *get_vdso_data(void)
static inline unsigned long get_vdso_data(void)
{
	return (const struct vdso_data *)(get_vdso_base()
			- VDSO_DATA_SIZE + SMP_CACHE_BYTES * NR_CPUS);
	return get_vdso_base() - VVAR_SIZE;
}

#endif /* __ASSEMBLY__ */
+1 −1
Original line number Diff line number Diff line
@@ -285,7 +285,7 @@ unsigned long stack_top(void)

	/* Space for the VDSO & data page */
	top -= PAGE_ALIGN(current->thread.vdso->size);
	top -= PAGE_SIZE;
	top -= VVAR_SIZE;

	/* Space to randomize the VDSO base */
	if (current->flags & PF_RANDOMIZE)
Loading