]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
powerpc/vdso: Add a page for non-time data
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Wed, 2 Oct 2024 08:39:28 +0000 (10:39 +0200)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 16 Oct 2024 00:08:20 +0000 (11:08 +1100)
The page containing VDSO time data is swapped with the one containing
TIME namespace data when a process uses a non-root time namespace.
For other data like powerpc specific data and RNG data, it means
tracking whether time namespace is the root one or not to know which
page to use.

Simplify the logic behind by moving time data out of first data page
so that the first data page which contains everything else always
remains the first page. Time data is in the second or third page
depending on selected time namespace.

While we are playing with get_datapage macro, directly take into
account the data offset inside the macro instead of adding that offset
afterwards.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://patch.msgid.link/0557d3ec898c1d0ea2fc59fa8757618e524c5d94.1727858295.git.christophe.leroy@csgroup.eu
arch/powerpc/include/asm/vdso_datapage.h
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vdso/cacheflush.S
arch/powerpc/kernel/vdso/datapage.S
arch/powerpc/kernel/vdso/getrandom.S
arch/powerpc/kernel/vdso/gettimeofday.S
arch/powerpc/kernel/vdso/vdso32.lds.S
arch/powerpc/kernel/vdso/vdso64.lds.S

index 248dee138f7bf5dc11a9490a97f4a3917bc46e92..33069afccb3c6d520ab04b48114d9ac1d8772d45 100644 (file)
@@ -82,8 +82,9 @@ struct vdso_arch_data {
        __u32 syscall_map[SYSCALL_MAP_SIZE];    /* Map of syscalls  */
        __u32 compat_syscall_map[SYSCALL_MAP_SIZE];     /* Map of compat syscalls */
 
-       struct vdso_data data[CS_BASES];
        struct vdso_rng_data rng_data;
+
+       struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
 };
 
 #else /* CONFIG_PPC64 */
@@ -95,8 +96,9 @@ struct vdso_arch_data {
        __u64 tb_ticks_per_sec;         /* Timebase tics / sec          0x38 */
        __u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
        __u32 compat_syscall_map[0];    /* No compat syscalls on PPC32 */
-       struct vdso_data data[CS_BASES];
        struct vdso_rng_data rng_data;
+
+       struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
 };
 
 #endif /* CONFIG_PPC64 */
@@ -105,29 +107,17 @@ extern struct vdso_arch_data *vdso_data;
 
 #else /* __ASSEMBLY__ */
 
-.macro get_datapage ptr
+.macro get_datapage ptr offset=0
        bcl     20, 31, .+4
 999:
        mflr    \ptr
-       addis   \ptr, \ptr, (_vdso_datapage - 999b)@ha
-       addi    \ptr, \ptr, (_vdso_datapage - 999b)@l
+       addis   \ptr, \ptr, (_vdso_datapage - 999b + \offset)@ha
+       addi    \ptr, \ptr, (_vdso_datapage - 999b + \offset)@l
 .endm
 
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
 
-.macro get_realdatapage ptr scratch
-       get_datapage \ptr
-#ifdef CONFIG_TIME_NS
-       lwz     \scratch, VDSO_CLOCKMODE_OFFSET(\ptr)
-       xoris   \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@h
-       xori    \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@l
-       cntlzw  \scratch, \scratch
-       rlwinm  \scratch, \scratch, PAGE_SHIFT - 5, 1 << PAGE_SHIFT
-       add     \ptr, \ptr, \scratch
-#endif
-.endm
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index ee4b9d676cff546caced78f6dd76923239697a3c..6166c1862c06ffdbbeab9f3fcc89efd9dc8f3187 100644 (file)
@@ -48,12 +48,13 @@ long sys_ni_syscall(void);
  */
 static union {
        struct vdso_arch_data   data;
-       u8                      page[PAGE_SIZE];
+       u8                      page[2 * PAGE_SIZE];
 } vdso_data_store __page_aligned_data;
 struct vdso_arch_data *vdso_data = &vdso_data_store.data;
 
 enum vvar_pages {
-       VVAR_DATA_PAGE_OFFSET,
+       VVAR_BASE_PAGE_OFFSET,
+       VVAR_TIME_PAGE_OFFSET,
        VVAR_TIMENS_PAGE_OFFSET,
        VVAR_NR_PAGES,
 };
@@ -119,7 +120,7 @@ static struct vm_special_mapping vdso64_spec __ro_after_init = {
 #ifdef CONFIG_TIME_NS
 struct vdso_data *arch_get_vdso_data(void *vvar_page)
 {
-       return ((struct vdso_arch_data *)vvar_page)->data;
+       return vvar_page;
 }
 
 /*
@@ -153,11 +154,14 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
        unsigned long pfn;
 
        switch (vmf->pgoff) {
-       case VVAR_DATA_PAGE_OFFSET:
+       case VVAR_BASE_PAGE_OFFSET:
+               pfn = virt_to_pfn(vdso_data);
+               break;
+       case VVAR_TIME_PAGE_OFFSET:
                if (timens_page)
                        pfn = page_to_pfn(timens_page);
                else
-                       pfn = virt_to_pfn(vdso_data);
+                       pfn = virt_to_pfn(vdso_data->data);
                break;
 #ifdef CONFIG_TIME_NS
        case VVAR_TIMENS_PAGE_OFFSET:
@@ -170,7 +174,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
                 */
                if (!timens_page)
                        return VM_FAULT_SIGBUS;
-               pfn = virt_to_pfn(vdso_data);
+               pfn = virt_to_pfn(vdso_data->data);
                break;
 #endif /* CONFIG_TIME_NS */
        default:
index 3b2479bd2f9a1d2e04e8eeb8fbcdff479e953d16..0085ae464dac9c32381625a6969a4e422ad34eb7 100644 (file)
@@ -30,7 +30,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 #ifdef CONFIG_PPC64
        mflr    r12
   .cfi_register lr,r12
-       get_realdatapage        r10, r11
+       get_datapage    r10
        mtlr    r12
   .cfi_restore lr
 #endif
index 2b19b6201a33a8f4a3b843a85fadc509d4e12788..db8e167f01667eb95b3dc74f6771e610411bba90 100644 (file)
@@ -28,7 +28,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
        mflr    r12
   .cfi_register lr,r12
        mr.     r4,r3
-       get_realdatapage        r3, r11
+       get_datapage    r3
        mtlr    r12
 #ifdef __powerpc64__
        addi    r3,r3,CFG_SYSCALL_MAP64
@@ -52,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
   .cfi_startproc
        mflr    r12
   .cfi_register lr,r12
-       get_realdatapage        r3, r11
+       get_datapage    r3
 #ifndef __powerpc64__
        lwz     r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
 #endif
index f3bbf931931ca22b9f350d2105b73fd54cf6d578..3deddcf89f99b481916923854b1c63b39c0f8cbe 100644 (file)
@@ -31,8 +31,7 @@
        PPC_STL         r2, PPC_MIN_STKFRM + STK_GOT(r1)
   .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
 #endif
-       get_realdatapage        r8, r11
-       addi            r8, r8, VDSO_RNG_DATA_OFFSET
+       get_datapage    r8 VDSO_RNG_DATA_OFFSET
        bl              CFUNC(DOTSYM(\funct))
        PPC_LL          r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
 #ifdef __powerpc64__
index 5540d7021fa25c32487fbab8193ca6dd4bc38d3e..5333848322ca6105018d501952e3bf42475f49df 100644 (file)
        PPC_STL         r2, PPC_MIN_STKFRM + STK_GOT(r1)
   .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
 #endif
-       get_datapage    r5
        .ifeq   \call_time
-       addi            r5, r5, VDSO_DATA_OFFSET
+               get_datapage    r5 VDSO_DATA_OFFSET
        .else
-       addi            r4, r5, VDSO_DATA_OFFSET
+               get_datapage    r4 VDSO_DATA_OFFSET
        .endif
        bl              CFUNC(DOTSYM(\funct))
        PPC_LL          r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
index 7b41d5d256e814adaaefd6d7f23e17ef9add697f..1a1b0b6d681a9977e4ef8042e52d8d33da61887e 100644 (file)
@@ -16,7 +16,7 @@ OUTPUT_ARCH(powerpc:common)
 
 SECTIONS
 {
-       PROVIDE(_vdso_datapage = . - 2 * PAGE_SIZE);
+       PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
        . = SIZEOF_HEADERS;
 
        .hash           : { *(.hash) }                  :text
index 9481e4b892ed139001cb544b3920832c7c76150e..e21b5506cad62b16e677be74fda7921ec917141a 100644 (file)
@@ -16,7 +16,7 @@ OUTPUT_ARCH(powerpc:common64)
 
 SECTIONS
 {
-       PROVIDE(_vdso_datapage = . - 2 * PAGE_SIZE);
+       PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
        . = SIZEOF_HEADERS;
 
        .hash           : { *(.hash) }                  :text