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 #ifndef __ASM_VDSO_VDSO_H 8 #define __ASM_VDSO_VDSO_H 9 10 #include <asm/sgidefs.h> 11 #include <vdso/page.h> 12 13 #define __VDSO_PAGES 4 14 15 #ifndef __ASSEMBLER__ 16 17 #include <asm/asm.h> 18 #include <asm/vdso.h> 19 20 static inline const struct vdso_time_data *get_vdso_time_data(void) 21 { 22 const struct vdso_time_data *addr; 23 24 /* 25 * We can't use cpu_has_mips_r6 since it needs the cpu_data[] 26 * kernel symbol. 27 */ 28 #ifdef CONFIG_CPU_MIPSR6 29 /* 30 * lapc <symbol> is an alias to addiupc reg, <symbol> - . 31 * 32 * We can't use addiupc because there is no label-label 33 * support for the addiupc reloc 34 */ 35 __asm__("lapc %0, vdso_u_time_data \n" 36 : "=r" (addr) : :); 37 #else 38 /* 39 * Get the base load address of the VDSO. We have to avoid generating 40 * relocations and references to the GOT because ld.so does not perform 41 * relocations on the VDSO. We use the current offset from the VDSO base 42 * and perform a PC-relative branch which gives the absolute address in 43 * ra, and take the difference. The assembler chokes on 44 * "li %0, _start - .", so embed the offset as a word and branch over 45 * it. 46 * 47 */ 48 49 __asm__( 50 " .set push \n" 51 " .set noreorder \n" 52 " bal 1f \n" 53 " nop \n" 54 " .word vdso_u_time_data - . \n" 55 "1: lw %0, 0($31) \n" 56 " " STR(PTR_ADDU) " %0, $31, %0 \n" 57 " .set pop \n" 58 : "=r" (addr) 59 : 60 : "$31"); 61 #endif /* CONFIG_CPU_MIPSR6 */ 62 63 return addr; 64 } 65 66 #ifdef CONFIG_CLKSRC_MIPS_GIC 67 68 static inline void __iomem *get_gic(const struct vdso_time_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 /* __ASSEMBLER__ */ 76 77 #endif /* __ASM_VDSO_VDSO_H */ 78