124640f23SVincenzo Frascino /* SPDX-License-Identifier: GPL-2.0-or-later */ 224640f23SVincenzo Frascino /* 324640f23SVincenzo Frascino * Copyright (C) 2015 Imagination Technologies 424640f23SVincenzo Frascino * Author: Alex Smith <alex.smith@imgtec.com> 524640f23SVincenzo Frascino */ 624640f23SVincenzo Frascino 724640f23SVincenzo Frascino #include <asm/sgidefs.h> 824640f23SVincenzo Frascino 924640f23SVincenzo Frascino #ifndef __ASSEMBLY__ 1024640f23SVincenzo Frascino 1124640f23SVincenzo Frascino #include <asm/asm.h> 1224640f23SVincenzo Frascino #include <asm/page.h> 1324640f23SVincenzo Frascino #include <asm/vdso.h> 1424640f23SVincenzo Frascino get_vdso_base(void)1524640f23SVincenzo Frascinostatic inline unsigned long get_vdso_base(void) 1624640f23SVincenzo Frascino { 1724640f23SVincenzo Frascino unsigned long addr; 1824640f23SVincenzo Frascino 1924640f23SVincenzo Frascino /* 2024640f23SVincenzo Frascino * We can't use cpu_has_mips_r6 since it needs the cpu_data[] 2124640f23SVincenzo Frascino * kernel symbol. 2224640f23SVincenzo Frascino */ 2324640f23SVincenzo Frascino #ifdef CONFIG_CPU_MIPSR6 2424640f23SVincenzo Frascino /* 2524640f23SVincenzo Frascino * lapc <symbol> is an alias to addiupc reg, <symbol> - . 2624640f23SVincenzo Frascino * 2724640f23SVincenzo Frascino * We can't use addiupc because there is no label-label 2824640f23SVincenzo Frascino * support for the addiupc reloc 2924640f23SVincenzo Frascino */ 3024640f23SVincenzo Frascino __asm__("lapc %0, _start \n" 3124640f23SVincenzo Frascino : "=r" (addr) : :); 3224640f23SVincenzo Frascino #else 3324640f23SVincenzo Frascino /* 3424640f23SVincenzo Frascino * Get the base load address of the VDSO. We have to avoid generating 3524640f23SVincenzo Frascino * relocations and references to the GOT because ld.so does not peform 3624640f23SVincenzo Frascino * relocations on the VDSO. We use the current offset from the VDSO base 3724640f23SVincenzo Frascino * and perform a PC-relative branch which gives the absolute address in 3824640f23SVincenzo Frascino * ra, and take the difference. The assembler chokes on 3924640f23SVincenzo Frascino * "li %0, _start - .", so embed the offset as a word and branch over 4024640f23SVincenzo Frascino * it. 4124640f23SVincenzo Frascino * 4224640f23SVincenzo Frascino */ 4324640f23SVincenzo Frascino 4424640f23SVincenzo Frascino __asm__( 4524640f23SVincenzo Frascino " .set push \n" 4624640f23SVincenzo Frascino " .set noreorder \n" 4724640f23SVincenzo Frascino " bal 1f \n" 4824640f23SVincenzo Frascino " nop \n" 4924640f23SVincenzo Frascino " .word _start - . \n" 5024640f23SVincenzo Frascino "1: lw %0, 0($31) \n" 5124640f23SVincenzo Frascino " " STR(PTR_ADDU) " %0, $31, %0 \n" 5224640f23SVincenzo Frascino " .set pop \n" 5324640f23SVincenzo Frascino : "=r" (addr) 5424640f23SVincenzo Frascino : 5524640f23SVincenzo Frascino : "$31"); 5624640f23SVincenzo Frascino #endif /* CONFIG_CPU_MIPSR6 */ 5724640f23SVincenzo Frascino 5824640f23SVincenzo Frascino return addr; 5924640f23SVincenzo Frascino } 6024640f23SVincenzo Frascino get_vdso_data(void)6124640f23SVincenzo Frascinostatic inline const struct vdso_data *get_vdso_data(void) 6224640f23SVincenzo Frascino { 6324640f23SVincenzo Frascino return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE); 6424640f23SVincenzo Frascino } 6524640f23SVincenzo Frascino 6624640f23SVincenzo Frascino #ifdef CONFIG_CLKSRC_MIPS_GIC 6724640f23SVincenzo Frascino get_gic(const struct vdso_data * data)6824640f23SVincenzo Frascinostatic inline void __iomem *get_gic(const struct vdso_data *data) 6924640f23SVincenzo Frascino { 70*47ce8527SMartin Fäcknitz return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE; 7124640f23SVincenzo Frascino } 7224640f23SVincenzo Frascino 7324640f23SVincenzo Frascino #endif /* CONFIG_CLKSRC_MIPS_GIC */ 7424640f23SVincenzo Frascino 7524640f23SVincenzo Frascino #endif /* __ASSEMBLY__ */ 76