mirror of https://github.com/torvalds/linux.git
MIPS: vdso: Switch to generic storage implementation
The generic storage implementation provides the same features as the custom one. However it can be shared between architectures, making maintenance easier. Co-developed-by: Nam Cao <namcao@linutronix.de> Signed-off-by: Nam Cao <namcao@linutronix.de> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20250204-vdso-store-rng-v3-13-13a4669dfc8c@linutronix.de
This commit is contained in:
parent
9bf39a65b2
commit
69896119dc
|
|
@ -51,6 +51,7 @@ config MIPS
|
|||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_IDLE_POLL_SETUP
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_VDSO_DATA_STORE
|
||||
select GUP_GET_PXX_LOW_HIGH if CPU_MIPS32 && PHYS_ADDR_T_64BIT
|
||||
select HAS_IOPORT if !NO_IOPORT_MAP || ISA
|
||||
select HAVE_ARCH_COMPILER_H
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ static __always_inline u64 read_r4k_count(void)
|
|||
|
||||
#ifdef CONFIG_CLKSRC_MIPS_GIC
|
||||
|
||||
static __always_inline u64 read_gic_count(const struct vdso_data *data)
|
||||
static __always_inline u64 read_gic_count(const struct vdso_time_data *data)
|
||||
{
|
||||
void __iomem *gic = get_gic(data);
|
||||
u32 hi, hi2, lo;
|
||||
|
|
@ -184,7 +184,7 @@ static __always_inline u64 read_gic_count(const struct vdso_data *data)
|
|||
#endif
|
||||
|
||||
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
|
||||
const struct vdso_data *vd)
|
||||
const struct vdso_time_data *vd)
|
||||
{
|
||||
#ifdef CONFIG_CSRC_R4K
|
||||
if (clock_mode == VDSO_CLOCKMODE_R4K)
|
||||
|
|
@ -209,10 +209,11 @@ static inline bool mips_vdso_hres_capable(void)
|
|||
}
|
||||
#define __arch_vdso_hres_capable mips_vdso_hres_capable
|
||||
|
||||
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
|
||||
static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void)
|
||||
{
|
||||
return get_vdso_data();
|
||||
return get_vdso_time_data();
|
||||
}
|
||||
#define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,18 @@
|
|||
*/
|
||||
|
||||
#include <asm/sgidefs.h>
|
||||
#include <vdso/page.h>
|
||||
|
||||
#define __VDSO_PAGES 4
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/vdso.h>
|
||||
|
||||
static inline unsigned long get_vdso_base(void)
|
||||
static inline const struct vdso_time_data *get_vdso_time_data(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
const struct vdso_time_data *addr;
|
||||
|
||||
/*
|
||||
* We can't use cpu_has_mips_r6 since it needs the cpu_data[]
|
||||
|
|
@ -27,7 +29,7 @@ static inline unsigned long get_vdso_base(void)
|
|||
* We can't use addiupc because there is no label-label
|
||||
* support for the addiupc reloc
|
||||
*/
|
||||
__asm__("lapc %0, _start \n"
|
||||
__asm__("lapc %0, vdso_u_time_data \n"
|
||||
: "=r" (addr) : :);
|
||||
#else
|
||||
/*
|
||||
|
|
@ -46,7 +48,7 @@ static inline unsigned long get_vdso_base(void)
|
|||
" .set noreorder \n"
|
||||
" bal 1f \n"
|
||||
" nop \n"
|
||||
" .word _start - . \n"
|
||||
" .word vdso_u_time_data - . \n"
|
||||
"1: lw %0, 0($31) \n"
|
||||
" " STR(PTR_ADDU) " %0, $31, %0 \n"
|
||||
" .set pop \n"
|
||||
|
|
@ -58,14 +60,9 @@ static inline unsigned long get_vdso_base(void)
|
|||
return addr;
|
||||
}
|
||||
|
||||
static inline const struct vdso_data *get_vdso_data(void)
|
||||
{
|
||||
return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CLKSRC_MIPS_GIC
|
||||
|
||||
static inline void __iomem *get_gic(const struct vdso_data *data)
|
||||
static inline void __iomem *get_gic(const struct vdso_time_data *data)
|
||||
{
|
||||
return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,12 @@
|
|||
#ifndef __ASM_VDSO_VSYSCALL_H
|
||||
#define __ASM_VDSO_VSYSCALL_H
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
extern struct vdso_data *vdso_data;
|
||||
|
||||
/*
|
||||
* Update the vDSO data page to keep in sync with kernel timekeeping.
|
||||
*/
|
||||
static __always_inline
|
||||
struct vdso_data *__mips_get_k_vdso_data(void)
|
||||
{
|
||||
return vdso_data;
|
||||
}
|
||||
#define __arch_get_k_vdso_data __mips_get_k_vdso_data
|
||||
|
||||
/* The asm-generic header needs to be included after the definitions above */
|
||||
#include <asm-generic/vdso/vsyscall.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/random.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vdso_datastore.h>
|
||||
|
||||
#include <asm/abi.h>
|
||||
#include <asm/mips-cps.h>
|
||||
|
|
@ -23,20 +24,7 @@
|
|||
#include <vdso/helpers.h>
|
||||
#include <vdso/vsyscall.h>
|
||||
|
||||
/* Kernel-provided data used by the VDSO. */
|
||||
static union vdso_data_store mips_vdso_data __page_aligned_data;
|
||||
struct vdso_data *vdso_data = mips_vdso_data.data;
|
||||
|
||||
/*
|
||||
* Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as
|
||||
* what we map and where within the area they are mapped is determined at
|
||||
* runtime.
|
||||
*/
|
||||
static struct page *no_pages[] = { NULL };
|
||||
static struct vm_special_mapping vdso_vvar_mapping = {
|
||||
.name = "[vvar]",
|
||||
.pages = no_pages,
|
||||
};
|
||||
static_assert(VDSO_NR_PAGES == __VDSO_PAGES);
|
||||
|
||||
static void __init init_vdso_image(struct mips_vdso_image *image)
|
||||
{
|
||||
|
|
@ -90,7 +78,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
|||
{
|
||||
struct mips_vdso_image *image = current->thread.abi->vdso;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr, gic_pfn, gic_base;
|
||||
unsigned long gic_size, size, base, data_addr, vdso_addr, gic_pfn, gic_base;
|
||||
struct vm_area_struct *vma;
|
||||
int ret;
|
||||
|
||||
|
|
@ -119,8 +107,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
|||
* the counter registers at the start.
|
||||
*/
|
||||
gic_size = mips_gic_present() ? PAGE_SIZE : 0;
|
||||
vvar_size = gic_size + PAGE_SIZE;
|
||||
size = vvar_size + image->size;
|
||||
size = gic_size + VDSO_NR_PAGES * PAGE_SIZE + image->size;
|
||||
|
||||
/*
|
||||
* Find a region that's large enough for us to perform the
|
||||
|
|
@ -143,15 +130,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
|||
*/
|
||||
if (cpu_has_dc_aliases) {
|
||||
base = __ALIGN_MASK(base, shm_align_mask);
|
||||
base += ((unsigned long)vdso_data - gic_size) & shm_align_mask;
|
||||
base += ((unsigned long)vdso_k_time_data - gic_size) & shm_align_mask;
|
||||
}
|
||||
|
||||
data_addr = base + gic_size;
|
||||
vdso_addr = data_addr + PAGE_SIZE;
|
||||
vdso_addr = data_addr + VDSO_NR_PAGES * PAGE_SIZE;
|
||||
|
||||
vma = _install_special_mapping(mm, base, vvar_size,
|
||||
VM_READ | VM_MAYREAD,
|
||||
&vdso_vvar_mapping);
|
||||
vma = vdso_install_vvar_mapping(mm, data_addr);
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
goto out;
|
||||
|
|
@ -161,6 +146,17 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
|||
if (gic_size) {
|
||||
gic_base = (unsigned long)mips_gic_base + MIPS_GIC_USER_OFS;
|
||||
gic_pfn = PFN_DOWN(__pa(gic_base));
|
||||
static const struct vm_special_mapping gic_mapping = {
|
||||
.name = "[gic]",
|
||||
.pages = (struct page **) { NULL },
|
||||
};
|
||||
|
||||
vma = _install_special_mapping(mm, base, gic_size, VM_READ | VM_MAYREAD,
|
||||
&gic_mapping);
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size,
|
||||
pgprot_noncached(vma->vm_page_prot));
|
||||
|
|
@ -168,13 +164,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Map data page. */
|
||||
ret = remap_pfn_range(vma, data_addr,
|
||||
virt_to_phys(vdso_data) >> PAGE_SHIFT,
|
||||
PAGE_SIZE, vma->vm_page_prot);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Map VDSO image. */
|
||||
vma = _install_special_mapping(mm, vdso_addr, image->size,
|
||||
VM_READ | VM_EXEC |
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <asm/sgidefs.h>
|
||||
#include <asm/vdso/vdso.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
||||
OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips")
|
||||
|
|
@ -18,7 +20,8 @@ OUTPUT_ARCH(mips)
|
|||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(_start = .);
|
||||
VDSO_VVAR_SYMS
|
||||
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue