1 /* 2 * Copyright (C) 2015 Imagination Technologies 3 * Author: Alex Smith <alex.smith@imgtec.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 */ 10 11 #include <asm/sgidefs.h> 12 13 #if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT) 14 15 /* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */ 16 #undef CONFIG_64BIT 17 #define CONFIG_32BIT 1 18 #ifndef __ASSEMBLY__ 19 #include <asm-generic/atomic64.h> 20 #endif 21 #endif 22 23 #ifndef __ASSEMBLY__ 24 25 #include <asm/asm.h> 26 #include <asm/page.h> 27 #include <asm/vdso.h> 28 get_vdso_base(void)29static inline unsigned long get_vdso_base(void) 30 { 31 unsigned long addr; 32 33 /* 34 * We can't use cpu_has_mips_r6 since it needs the cpu_data[] 35 * kernel symbol. 36 */ 37 #ifdef CONFIG_CPU_MIPSR6 38 /* 39 * lapc <symbol> is an alias to addiupc reg, <symbol> - . 40 * 41 * We can't use addiupc because there is no label-label 42 * support for the addiupc reloc 43 */ 44 __asm__("lapc %0, _start \n" 45 : "=r" (addr) : :); 46 #else 47 /* 48 * Get the base load address of the VDSO. We have to avoid generating 49 * relocations and references to the GOT because ld.so does not peform 50 * relocations on the VDSO. We use the current offset from the VDSO base 51 * and perform a PC-relative branch which gives the absolute address in 52 * ra, and take the difference. The assembler chokes on 53 * "li %0, _start - .", so embed the offset as a word and branch over 54 * it. 55 * 56 */ 57 58 __asm__( 59 " .set push \n" 60 " .set noreorder \n" 61 " bal 1f \n" 62 " nop \n" 63 " .word _start - . \n" 64 "1: lw %0, 0($31) \n" 65 " " STR(PTR_ADDU) " %0, $31, %0 \n" 66 " .set pop \n" 67 : "=r" (addr) 68 : 69 : "$31"); 70 #endif /* CONFIG_CPU_MIPSR6 */ 71 72 return addr; 73 } 74 get_vdso_data(void)75static inline const union mips_vdso_data *get_vdso_data(void) 76 { 77 return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE); 78 } 79 80 #ifdef CONFIG_CLKSRC_MIPS_GIC 81 get_gic(const union mips_vdso_data * data)82static inline void __iomem *get_gic(const union mips_vdso_data *data) 83 { 84 return (void __iomem *)data - PAGE_SIZE; 85 } 86 87 #endif /* CONFIG_CLKSRC_MIPS_GIC */ 88 89 #endif /* __ASSEMBLY__ */ 90