1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Userland implementation of gettimeofday() for processes 4 * for use in the vDSO 5 * 6 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org, 7 * IBM Corp. 8 */ 9#include <asm/processor.h> 10#include <asm/ppc_asm.h> 11#include <asm/vdso.h> 12#include <asm/vdso_datapage.h> 13#include <asm/asm-offsets.h> 14#include <asm/unistd.h> 15 16/* 17 * The macro sets two stack frames, one for the caller and one for the callee 18 * because there are no requirement for the caller to set a stack frame when 19 * calling VDSO so it may have omitted to set one, especially on PPC64 20 */ 21 22.macro cvdso_call funct call_time=0 23 .cfi_startproc 24 PPC_STLU r1, -PPC_MIN_STKFRM(r1) 25 .cfi_adjust_cfa_offset PPC_MIN_STKFRM 26 mflr r0 27 PPC_STLU r1, -PPC_MIN_STKFRM(r1) 28 .cfi_adjust_cfa_offset PPC_MIN_STKFRM 29 PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 30 .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF 31#ifdef __powerpc64__ 32 PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) 33 .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT 34#endif 35 get_datapage r5 36 .ifeq \call_time 37 addi r5, r5, VDSO_DATA_OFFSET 38 .else 39 addi r4, r5, VDSO_DATA_OFFSET 40 .endif 41 bl DOTSYM(\funct) 42 PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 43#ifdef __powerpc64__ 44 PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) 45 .cfi_restore r2 46#endif 47 .ifeq \call_time 48 cmpwi r3, 0 49 .endif 50 mtlr r0 51 addi r1, r1, 2 * PPC_MIN_STKFRM 52 .cfi_restore lr 53 .cfi_def_cfa_offset 0 54 crclr so 55 .ifeq \call_time 56 beqlr+ 57 crset so 58 neg r3, r3 59 .endif 60 blr 61 .cfi_endproc 62.endm 63 64 .text 65/* 66 * Exact prototype of gettimeofday 67 * 68 * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); 69 * 70 */ 71V_FUNCTION_BEGIN(__kernel_gettimeofday) 72 cvdso_call __c_kernel_gettimeofday 73V_FUNCTION_END(__kernel_gettimeofday) 74 75/* 76 * Exact prototype of clock_gettime() 77 * 78 * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); 79 * 80 */ 81V_FUNCTION_BEGIN(__kernel_clock_gettime) 82 cvdso_call __c_kernel_clock_gettime 83V_FUNCTION_END(__kernel_clock_gettime) 84 85/* 86 * Exact prototype of clock_gettime64() 87 * 88 * int __kernel_clock_gettime64(clockid_t clock_id, struct __timespec64 *ts); 89 * 90 */ 91#ifndef __powerpc64__ 92V_FUNCTION_BEGIN(__kernel_clock_gettime64) 93 cvdso_call __c_kernel_clock_gettime64 94V_FUNCTION_END(__kernel_clock_gettime64) 95#endif 96 97/* 98 * Exact prototype of clock_getres() 99 * 100 * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); 101 * 102 */ 103V_FUNCTION_BEGIN(__kernel_clock_getres) 104 cvdso_call __c_kernel_clock_getres 105V_FUNCTION_END(__kernel_clock_getres) 106 107 108/* 109 * Exact prototype of time() 110 * 111 * time_t time(time *t); 112 * 113 */ 114V_FUNCTION_BEGIN(__kernel_time) 115 cvdso_call __c_kernel_time call_time=1 116V_FUNCTION_END(__kernel_time) 117 118/* Routines for restoring integer registers, called by the compiler. */ 119/* Called with r11 pointing to the stack header word of the caller of the */ 120/* function, just beyond the end of the integer restore area. */ 121#ifndef __powerpc64__ 122_GLOBAL(_restgpr_31_x) 123_GLOBAL(_rest32gpr_31_x) 124 lwz r0,4(r11) 125 lwz r31,-4(r11) 126 mtlr r0 127 mr r1,r11 128 blr 129#endif 130