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

nsleep-lat.c (4387B)


      1/* Measure nanosleep timer latency
      2 *              by: john stultz (john.stultz@linaro.org)
      3 *		(C) Copyright Linaro 2013
      4 *              Licensed under the GPLv2
      5 *
      6 *  To build:
      7 *	$ gcc nsleep-lat.c -o nsleep-lat -lrt
      8 *
      9 *   This program is free software: you can redistribute it and/or modify
     10 *   it under the terms of the GNU General Public License as published by
     11 *   the Free Software Foundation, either version 2 of the License, or
     12 *   (at your option) any later version.
     13 *
     14 *   This program is distributed in the hope that it will be useful,
     15 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 *   GNU General Public License for more details.
     18 */
     19
     20#include <stdio.h>
     21#include <stdlib.h>
     22#include <time.h>
     23#include <sys/time.h>
     24#include <sys/timex.h>
     25#include <string.h>
     26#include <signal.h>
     27#include "../kselftest.h"
     28
     29#define NSEC_PER_SEC 1000000000ULL
     30
     31#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
     32
     33
     34#define CLOCK_REALTIME			0
     35#define CLOCK_MONOTONIC			1
     36#define CLOCK_PROCESS_CPUTIME_ID	2
     37#define CLOCK_THREAD_CPUTIME_ID		3
     38#define CLOCK_MONOTONIC_RAW		4
     39#define CLOCK_REALTIME_COARSE		5
     40#define CLOCK_MONOTONIC_COARSE		6
     41#define CLOCK_BOOTTIME			7
     42#define CLOCK_REALTIME_ALARM		8
     43#define CLOCK_BOOTTIME_ALARM		9
     44#define CLOCK_HWSPECIFIC		10
     45#define CLOCK_TAI			11
     46#define NR_CLOCKIDS			12
     47
     48#define UNSUPPORTED 0xf00f
     49
     50char *clockstring(int clockid)
     51{
     52	switch (clockid) {
     53	case CLOCK_REALTIME:
     54		return "CLOCK_REALTIME";
     55	case CLOCK_MONOTONIC:
     56		return "CLOCK_MONOTONIC";
     57	case CLOCK_PROCESS_CPUTIME_ID:
     58		return "CLOCK_PROCESS_CPUTIME_ID";
     59	case CLOCK_THREAD_CPUTIME_ID:
     60		return "CLOCK_THREAD_CPUTIME_ID";
     61	case CLOCK_MONOTONIC_RAW:
     62		return "CLOCK_MONOTONIC_RAW";
     63	case CLOCK_REALTIME_COARSE:
     64		return "CLOCK_REALTIME_COARSE";
     65	case CLOCK_MONOTONIC_COARSE:
     66		return "CLOCK_MONOTONIC_COARSE";
     67	case CLOCK_BOOTTIME:
     68		return "CLOCK_BOOTTIME";
     69	case CLOCK_REALTIME_ALARM:
     70		return "CLOCK_REALTIME_ALARM";
     71	case CLOCK_BOOTTIME_ALARM:
     72		return "CLOCK_BOOTTIME_ALARM";
     73	case CLOCK_TAI:
     74		return "CLOCK_TAI";
     75	};
     76	return "UNKNOWN_CLOCKID";
     77}
     78
     79struct timespec timespec_add(struct timespec ts, unsigned long long ns)
     80{
     81	ts.tv_nsec += ns;
     82	while (ts.tv_nsec >= NSEC_PER_SEC) {
     83		ts.tv_nsec -= NSEC_PER_SEC;
     84		ts.tv_sec++;
     85	}
     86	return ts;
     87}
     88
     89
     90long long timespec_sub(struct timespec a, struct timespec b)
     91{
     92	long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
     93
     94	ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
     95	return ret;
     96}
     97
     98int nanosleep_lat_test(int clockid, long long ns)
     99{
    100	struct timespec start, end, target;
    101	long long latency = 0;
    102	int i, count;
    103
    104	target.tv_sec = ns/NSEC_PER_SEC;
    105	target.tv_nsec = ns%NSEC_PER_SEC;
    106
    107	if (clock_gettime(clockid, &start))
    108		return UNSUPPORTED;
    109	if (clock_nanosleep(clockid, 0, &target, NULL))
    110		return UNSUPPORTED;
    111
    112	count = 10;
    113
    114	/* First check relative latency */
    115	clock_gettime(clockid, &start);
    116	for (i = 0; i < count; i++)
    117		clock_nanosleep(clockid, 0, &target, NULL);
    118	clock_gettime(clockid, &end);
    119
    120	if (((timespec_sub(start, end)/count)-ns) > UNRESONABLE_LATENCY) {
    121		printf("Large rel latency: %lld ns :", (timespec_sub(start, end)/count)-ns);
    122		return -1;
    123	}
    124
    125	/* Next check absolute latency */
    126	for (i = 0; i < count; i++) {
    127		clock_gettime(clockid, &start);
    128		target = timespec_add(start, ns);
    129		clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL);
    130		clock_gettime(clockid, &end);
    131		latency += timespec_sub(target, end);
    132	}
    133
    134	if (latency/count > UNRESONABLE_LATENCY) {
    135		printf("Large abs latency: %lld ns :", latency/count);
    136		return -1;
    137	}
    138
    139	return 0;
    140}
    141
    142
    143
    144int main(int argc, char **argv)
    145{
    146	long long length;
    147	int clockid, ret;
    148
    149	for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
    150
    151		/* Skip cputime clockids since nanosleep won't increment cputime */
    152		if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
    153				clockid == CLOCK_THREAD_CPUTIME_ID ||
    154				clockid == CLOCK_HWSPECIFIC)
    155			continue;
    156
    157		printf("nsleep latency %-26s ", clockstring(clockid));
    158		fflush(stdout);
    159
    160		length = 10;
    161		while (length <= (NSEC_PER_SEC * 10)) {
    162			ret = nanosleep_lat_test(clockid, length);
    163			if (ret)
    164				break;
    165			length *= 100;
    166
    167		}
    168
    169		if (ret == UNSUPPORTED) {
    170			printf("[UNSUPPORTED]\n");
    171			continue;
    172		}
    173		if (ret < 0) {
    174			printf("[FAILED]\n");
    175			return ksft_exit_fail();
    176		}
    177		printf("[OK]\n");
    178	}
    179	return ksft_exit_pass();
    180}