18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015 Imagination Technologies 48c2ecf20Sopenharmony_ci * Author: Alex Smith <alex.smith@imgtec.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <asm/sgidefs.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/asm.h> 128c2ecf20Sopenharmony_ci#include <asm/page.h> 138c2ecf20Sopenharmony_ci#include <asm/vdso.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic inline unsigned long get_vdso_base(void) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci unsigned long addr; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci /* 208c2ecf20Sopenharmony_ci * We can't use cpu_has_mips_r6 since it needs the cpu_data[] 218c2ecf20Sopenharmony_ci * kernel symbol. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_MIPSR6 248c2ecf20Sopenharmony_ci /* 258c2ecf20Sopenharmony_ci * lapc <symbol> is an alias to addiupc reg, <symbol> - . 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * We can't use addiupc because there is no label-label 288c2ecf20Sopenharmony_ci * support for the addiupc reloc 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci __asm__("lapc %0, _start \n" 318c2ecf20Sopenharmony_ci : "=r" (addr) : :); 328c2ecf20Sopenharmony_ci#else 338c2ecf20Sopenharmony_ci /* 348c2ecf20Sopenharmony_ci * Get the base load address of the VDSO. We have to avoid generating 358c2ecf20Sopenharmony_ci * relocations and references to the GOT because ld.so does not peform 368c2ecf20Sopenharmony_ci * relocations on the VDSO. We use the current offset from the VDSO base 378c2ecf20Sopenharmony_ci * and perform a PC-relative branch which gives the absolute address in 388c2ecf20Sopenharmony_ci * ra, and take the difference. The assembler chokes on 398c2ecf20Sopenharmony_ci * "li %0, _start - .", so embed the offset as a word and branch over 408c2ecf20Sopenharmony_ci * it. 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci __asm__( 458c2ecf20Sopenharmony_ci " .set push \n" 468c2ecf20Sopenharmony_ci " .set noreorder \n" 478c2ecf20Sopenharmony_ci " bal 1f \n" 488c2ecf20Sopenharmony_ci " nop \n" 498c2ecf20Sopenharmony_ci " .word _start - . \n" 508c2ecf20Sopenharmony_ci "1: lw %0, 0($31) \n" 518c2ecf20Sopenharmony_ci " " STR(PTR_ADDU) " %0, $31, %0 \n" 528c2ecf20Sopenharmony_ci " .set pop \n" 538c2ecf20Sopenharmony_ci : "=r" (addr) 548c2ecf20Sopenharmony_ci : 558c2ecf20Sopenharmony_ci : "$31"); 568c2ecf20Sopenharmony_ci#endif /* CONFIG_CPU_MIPSR6 */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return addr; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic inline const struct vdso_data *get_vdso_data(void) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#ifdef CONFIG_CLKSRC_MIPS_GIC 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic inline void __iomem *get_gic(const struct vdso_data *data) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#endif /* CONFIG_CLKSRC_MIPS_GIC */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 76