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