mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
powerpc/vdso: Add a page for non-time data
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
This commit is contained in:
parent
8cf0b93919
commit
c39b1dcf05
8 changed files with 25 additions and 33 deletions
|
@ -82,8 +82,9 @@ struct vdso_arch_data {
|
||||||
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
||||||
__u32 compat_syscall_map[SYSCALL_MAP_SIZE]; /* Map of compat 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_rng_data rng_data;
|
||||||
|
|
||||||
|
struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
|
||||||
};
|
};
|
||||||
|
|
||||||
#else /* CONFIG_PPC64 */
|
#else /* CONFIG_PPC64 */
|
||||||
|
@ -95,8 +96,9 @@ struct vdso_arch_data {
|
||||||
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
|
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
|
||||||
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
||||||
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
|
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
|
||||||
struct vdso_data data[CS_BASES];
|
|
||||||
struct vdso_rng_data rng_data;
|
struct vdso_rng_data rng_data;
|
||||||
|
|
||||||
|
struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_PPC64 */
|
#endif /* CONFIG_PPC64 */
|
||||||
|
@ -105,29 +107,17 @@ extern struct vdso_arch_data *vdso_data;
|
||||||
|
|
||||||
#else /* __ASSEMBLY__ */
|
#else /* __ASSEMBLY__ */
|
||||||
|
|
||||||
.macro get_datapage ptr
|
.macro get_datapage ptr offset=0
|
||||||
bcl 20, 31, .+4
|
bcl 20, 31, .+4
|
||||||
999:
|
999:
|
||||||
mflr \ptr
|
mflr \ptr
|
||||||
addis \ptr, \ptr, (_vdso_datapage - 999b)@ha
|
addis \ptr, \ptr, (_vdso_datapage - 999b + \offset)@ha
|
||||||
addi \ptr, \ptr, (_vdso_datapage - 999b)@l
|
addi \ptr, \ptr, (_vdso_datapage - 999b + \offset)@l
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/page.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 /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
|
@ -48,12 +48,13 @@ long sys_ni_syscall(void);
|
||||||
*/
|
*/
|
||||||
static union {
|
static union {
|
||||||
struct vdso_arch_data data;
|
struct vdso_arch_data data;
|
||||||
u8 page[PAGE_SIZE];
|
u8 page[2 * PAGE_SIZE];
|
||||||
} vdso_data_store __page_aligned_data;
|
} vdso_data_store __page_aligned_data;
|
||||||
struct vdso_arch_data *vdso_data = &vdso_data_store.data;
|
struct vdso_arch_data *vdso_data = &vdso_data_store.data;
|
||||||
|
|
||||||
enum vvar_pages {
|
enum vvar_pages {
|
||||||
VVAR_DATA_PAGE_OFFSET,
|
VVAR_BASE_PAGE_OFFSET,
|
||||||
|
VVAR_TIME_PAGE_OFFSET,
|
||||||
VVAR_TIMENS_PAGE_OFFSET,
|
VVAR_TIMENS_PAGE_OFFSET,
|
||||||
VVAR_NR_PAGES,
|
VVAR_NR_PAGES,
|
||||||
};
|
};
|
||||||
|
@ -119,7 +120,7 @@ static struct vm_special_mapping vdso64_spec __ro_after_init = {
|
||||||
#ifdef CONFIG_TIME_NS
|
#ifdef CONFIG_TIME_NS
|
||||||
struct vdso_data *arch_get_vdso_data(void *vvar_page)
|
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;
|
unsigned long pfn;
|
||||||
|
|
||||||
switch (vmf->pgoff) {
|
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)
|
if (timens_page)
|
||||||
pfn = page_to_pfn(timens_page);
|
pfn = page_to_pfn(timens_page);
|
||||||
else
|
else
|
||||||
pfn = virt_to_pfn(vdso_data);
|
pfn = virt_to_pfn(vdso_data->data);
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_TIME_NS
|
#ifdef CONFIG_TIME_NS
|
||||||
case VVAR_TIMENS_PAGE_OFFSET:
|
case VVAR_TIMENS_PAGE_OFFSET:
|
||||||
|
@ -170,7 +174,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
||||||
*/
|
*/
|
||||||
if (!timens_page)
|
if (!timens_page)
|
||||||
return VM_FAULT_SIGBUS;
|
return VM_FAULT_SIGBUS;
|
||||||
pfn = virt_to_pfn(vdso_data);
|
pfn = virt_to_pfn(vdso_data->data);
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_TIME_NS */
|
#endif /* CONFIG_TIME_NS */
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -30,7 +30,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
mflr r12
|
mflr r12
|
||||||
.cfi_register lr,r12
|
.cfi_register lr,r12
|
||||||
get_realdatapage r10, r11
|
get_datapage r10
|
||||||
mtlr r12
|
mtlr r12
|
||||||
.cfi_restore lr
|
.cfi_restore lr
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,7 +28,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
|
||||||
mflr r12
|
mflr r12
|
||||||
.cfi_register lr,r12
|
.cfi_register lr,r12
|
||||||
mr. r4,r3
|
mr. r4,r3
|
||||||
get_realdatapage r3, r11
|
get_datapage r3
|
||||||
mtlr r12
|
mtlr r12
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
addi r3,r3,CFG_SYSCALL_MAP64
|
addi r3,r3,CFG_SYSCALL_MAP64
|
||||||
|
@ -52,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
mflr r12
|
mflr r12
|
||||||
.cfi_register lr,r12
|
.cfi_register lr,r12
|
||||||
get_realdatapage r3, r11
|
get_datapage r3
|
||||||
#ifndef __powerpc64__
|
#ifndef __powerpc64__
|
||||||
lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
|
lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,8 +31,7 @@
|
||||||
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||||
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
||||||
#endif
|
#endif
|
||||||
get_realdatapage r8, r11
|
get_datapage r8 VDSO_RNG_DATA_OFFSET
|
||||||
addi r8, r8, VDSO_RNG_DATA_OFFSET
|
|
||||||
bl CFUNC(DOTSYM(\funct))
|
bl CFUNC(DOTSYM(\funct))
|
||||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
|
|
|
@ -32,11 +32,10 @@
|
||||||
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||||
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
||||||
#endif
|
#endif
|
||||||
get_datapage r5
|
|
||||||
.ifeq \call_time
|
.ifeq \call_time
|
||||||
addi r5, r5, VDSO_DATA_OFFSET
|
get_datapage r5 VDSO_DATA_OFFSET
|
||||||
.else
|
.else
|
||||||
addi r4, r5, VDSO_DATA_OFFSET
|
get_datapage r4 VDSO_DATA_OFFSET
|
||||||
.endif
|
.endif
|
||||||
bl CFUNC(DOTSYM(\funct))
|
bl CFUNC(DOTSYM(\funct))
|
||||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||||
|
|
|
@ -16,7 +16,7 @@ OUTPUT_ARCH(powerpc:common)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
PROVIDE(_vdso_datapage = . - 2 * PAGE_SIZE);
|
PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
|
||||||
. = SIZEOF_HEADERS;
|
. = SIZEOF_HEADERS;
|
||||||
|
|
||||||
.hash : { *(.hash) } :text
|
.hash : { *(.hash) } :text
|
||||||
|
|
|
@ -16,7 +16,7 @@ OUTPUT_ARCH(powerpc:common64)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
PROVIDE(_vdso_datapage = . - 2 * PAGE_SIZE);
|
PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
|
||||||
. = SIZEOF_HEADERS;
|
. = SIZEOF_HEADERS;
|
||||||
|
|
||||||
.hash : { *(.hash) } :text
|
.hash : { *(.hash) } :text
|
||||||
|
|
Loading…
Add table
Reference in a new issue