cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

time.c (2577B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
      4 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
      5 * Copyright (C) 2012-2014 Cisco Systems
      6 * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
      7 */
      8
      9#include <stddef.h>
     10#include <unistd.h>
     11#include <errno.h>
     12#include <signal.h>
     13#include <time.h>
     14#include <sys/time.h>
     15#include <kern_util.h>
     16#include <os.h>
     17#include <string.h>
     18
     19static timer_t event_high_res_timer = 0;
     20
     21static inline long long timespec_to_ns(const struct timespec *ts)
     22{
     23	return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec;
     24}
     25
     26long long os_persistent_clock_emulation(void)
     27{
     28	struct timespec realtime_tp;
     29
     30	clock_gettime(CLOCK_REALTIME, &realtime_tp);
     31	return timespec_to_ns(&realtime_tp);
     32}
     33
     34/**
     35 * os_timer_create() - create an new posix (interval) timer
     36 */
     37int os_timer_create(void)
     38{
     39	timer_t *t = &event_high_res_timer;
     40
     41	if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1)
     42		return -1;
     43
     44	return 0;
     45}
     46
     47int os_timer_set_interval(unsigned long long nsecs)
     48{
     49	struct itimerspec its;
     50
     51	its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC;
     52	its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC;
     53
     54	its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC;
     55	its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC;
     56
     57	if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1)
     58		return -errno;
     59
     60	return 0;
     61}
     62
     63int os_timer_one_shot(unsigned long long nsecs)
     64{
     65	struct itimerspec its = {
     66		.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC,
     67		.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC,
     68
     69		.it_interval.tv_sec = 0,
     70		.it_interval.tv_nsec = 0, // we cheat here
     71	};
     72
     73	timer_settime(event_high_res_timer, 0, &its, NULL);
     74	return 0;
     75}
     76
     77/**
     78 * os_timer_disable() - disable the posix (interval) timer
     79 */
     80void os_timer_disable(void)
     81{
     82	struct itimerspec its;
     83
     84	memset(&its, 0, sizeof(struct itimerspec));
     85	timer_settime(event_high_res_timer, 0, &its, NULL);
     86}
     87
     88long long os_nsecs(void)
     89{
     90	struct timespec ts;
     91
     92	clock_gettime(CLOCK_MONOTONIC,&ts);
     93	return timespec_to_ns(&ts);
     94}
     95
     96/**
     97 * os_idle_sleep() - sleep until interrupted
     98 */
     99void os_idle_sleep(void)
    100{
    101	struct itimerspec its;
    102	sigset_t set, old;
    103
    104	/* block SIGALRM while we analyze the timer state */
    105	sigemptyset(&set);
    106	sigaddset(&set, SIGALRM);
    107	sigprocmask(SIG_BLOCK, &set, &old);
    108
    109	/* check the timer, and if it'll fire then wait for it */
    110	timer_gettime(event_high_res_timer, &its);
    111	if (its.it_value.tv_sec || its.it_value.tv_nsec)
    112		sigsuspend(&old);
    113	/* either way, restore the signal mask */
    114	sigprocmask(SIG_UNBLOCK, &set, NULL);
    115}