Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Copyright (C) 2015 Imagination Technologies
0004  * Author: Alex Smith <alex.smith@imgtec.com>
0005  */
0006 
0007 #include <asm/sgidefs.h>
0008 
0009 #ifndef __ASSEMBLY__
0010 
0011 #include <asm/asm.h>
0012 #include <asm/page.h>
0013 #include <asm/vdso.h>
0014 
0015 static inline unsigned long get_vdso_base(void)
0016 {
0017     unsigned long addr;
0018 
0019     /*
0020      * We can't use cpu_has_mips_r6 since it needs the cpu_data[]
0021      * kernel symbol.
0022      */
0023 #ifdef CONFIG_CPU_MIPSR6
0024     /*
0025      * lapc <symbol> is an alias to addiupc reg, <symbol> - .
0026      *
0027      * We can't use addiupc because there is no label-label
0028      * support for the addiupc reloc
0029      */
0030     __asm__("lapc   %0, _start          \n"
0031         : "=r" (addr) : :);
0032 #else
0033     /*
0034      * Get the base load address of the VDSO. We have to avoid generating
0035      * relocations and references to the GOT because ld.so does not peform
0036      * relocations on the VDSO. We use the current offset from the VDSO base
0037      * and perform a PC-relative branch which gives the absolute address in
0038      * ra, and take the difference. The assembler chokes on
0039      * "li %0, _start - .", so embed the offset as a word and branch over
0040      * it.
0041      *
0042      */
0043 
0044     __asm__(
0045     "   .set push               \n"
0046     "   .set noreorder              \n"
0047     "   bal 1f              \n"
0048     "    nop                    \n"
0049     "   .word   _start - .          \n"
0050     "1: lw  %0, 0($31)          \n"
0051     "   " STR(PTR_ADDU) " %0, $31, %0       \n"
0052     "   .set pop                \n"
0053     : "=r" (addr)
0054     :
0055     : "$31");
0056 #endif /* CONFIG_CPU_MIPSR6 */
0057 
0058     return addr;
0059 }
0060 
0061 static inline const struct vdso_data *get_vdso_data(void)
0062 {
0063     return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE);
0064 }
0065 
0066 #ifdef CONFIG_CLKSRC_MIPS_GIC
0067 
0068 static inline void __iomem *get_gic(const struct vdso_data *data)
0069 {
0070     return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE;
0071 }
0072 
0073 #endif /* CONFIG_CLKSRC_MIPS_GIC */
0074 
0075 #endif /* __ASSEMBLY__ */