1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Copyright (C) 2015 Imagination Technologies 4 * Author: Alex Smith <alex.smith@imgtec.com> 5 */ 6 7 #include <asm/sgidefs.h> 8 9 #ifndef __ASSEMBLY__ 10 11 #include <asm/asm.h> 12 #include <asm/page.h> 13 #include <asm/vdso.h> 14 15 static inline unsigned long get_vdso_base(void) 16 { 17 unsigned long addr; 18 19 /* 20 * We can't use cpu_has_mips_r6 since it needs the cpu_data[] 21 * kernel symbol. 22 */ 23 #ifdef CONFIG_CPU_MIPSR6 24 /* 25 * lapc <symbol> is an alias to addiupc reg, <symbol> - . 26 * 27 * We can't use addiupc because there is no label-label 28 * support for the addiupc reloc 29 */ 30 __asm__("lapc %0, _start \n" 31 : "=r" (addr) : :); 32 #else 33 /* 34 * Get the base load address of the VDSO. We have to avoid generating 35 * relocations and references to the GOT because ld.so does not peform 36 * relocations on the VDSO. We use the current offset from the VDSO base 37 * and perform a PC-relative branch which gives the absolute address in 38 * ra, and take the difference. The assembler chokes on 39 * "li %0, _start - .", so embed the offset as a word and branch over 40 * it. 41 * 42 */ 43 44 __asm__( 45 " .set push \n" 46 " .set noreorder \n" 47 " bal 1f \n" 48 " nop \n" 49 " .word _start - . \n" 50 "1: lw %0, 0($31) \n" 51 " " STR(PTR_ADDU) " %0, $31, %0 \n" 52 " .set pop \n" 53 : "=r" (addr) 54 : 55 : "$31"); 56 #endif /* CONFIG_CPU_MIPSR6 */ 57 58 return addr; 59 } 60 61 static inline const struct vdso_data *get_vdso_data(void) 62 { 63 return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE); 64 } 65 66 #ifdef CONFIG_CLKSRC_MIPS_GIC 67 68 static inline void __iomem *get_gic(const struct vdso_data *data) 69 { 70 return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE; 71 } 72 73 #endif /* CONFIG_CLKSRC_MIPS_GIC */ 74 75 #endif /* __ASSEMBLY__ */ 76