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

raw_skew.c (3678B)


      1/* CLOCK_MONOTONIC vs CLOCK_MONOTONIC_RAW skew test
      2 *		by: john stultz (johnstul@us.ibm.com)
      3 *		    John Stultz <john.stultz@linaro.org>
      4 *		(C) Copyright IBM 2012
      5 *		(C) Copyright Linaro Limited 2015
      6 *		Licensed under the GPLv2
      7 *
      8 *  To build:
      9 *	$ gcc raw_skew.c -o raw_skew -lrt
     10 *
     11 *   This program is free software: you can redistribute it and/or modify
     12 *   it under the terms of the GNU General Public License as published by
     13 *   the Free Software Foundation, either version 2 of the License, or
     14 *   (at your option) any later version.
     15 *
     16 *   This program is distributed in the hope that it will be useful,
     17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 *   GNU General Public License for more details.
     20 */
     21
     22#include <stdio.h>
     23#include <unistd.h>
     24#include <stdlib.h>
     25#include <sys/time.h>
     26#include <sys/timex.h>
     27#include <time.h>
     28#include "../kselftest.h"
     29
     30#define CLOCK_MONOTONIC_RAW		4
     31#define NSEC_PER_SEC 1000000000LL
     32
     33#define shift_right(x, s) ({		\
     34	__typeof__(x) __x = (x);	\
     35	__typeof__(s) __s = (s);	\
     36	__x < 0 ? -(-__x >> __s) : __x >> __s; \
     37})
     38
     39long long llabs(long long val)
     40{
     41	if (val < 0)
     42		val = -val;
     43	return val;
     44}
     45
     46unsigned long long ts_to_nsec(struct timespec ts)
     47{
     48	return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
     49}
     50
     51struct timespec nsec_to_ts(long long ns)
     52{
     53	struct timespec ts;
     54
     55	ts.tv_sec = ns/NSEC_PER_SEC;
     56	ts.tv_nsec = ns%NSEC_PER_SEC;
     57	return ts;
     58}
     59
     60long long diff_timespec(struct timespec start, struct timespec end)
     61{
     62	long long start_ns, end_ns;
     63
     64	start_ns = ts_to_nsec(start);
     65	end_ns = ts_to_nsec(end);
     66	return end_ns - start_ns;
     67}
     68
     69void get_monotonic_and_raw(struct timespec *mon, struct timespec *raw)
     70{
     71	struct timespec start, mid, end;
     72	long long diff = 0, tmp;
     73	int i;
     74
     75	for (i = 0; i < 3; i++) {
     76		long long newdiff;
     77
     78		clock_gettime(CLOCK_MONOTONIC, &start);
     79		clock_gettime(CLOCK_MONOTONIC_RAW, &mid);
     80		clock_gettime(CLOCK_MONOTONIC, &end);
     81
     82		newdiff = diff_timespec(start, end);
     83		if (diff == 0 || newdiff < diff) {
     84			diff = newdiff;
     85			*raw = mid;
     86			tmp = (ts_to_nsec(start) + ts_to_nsec(end))/2;
     87			*mon = nsec_to_ts(tmp);
     88		}
     89	}
     90}
     91
     92int main(int argv, char **argc)
     93{
     94	struct timespec mon, raw, start, end;
     95	long long delta1, delta2, interval, eppm, ppm;
     96	struct timex tx1, tx2;
     97
     98	setbuf(stdout, NULL);
     99
    100	if (clock_gettime(CLOCK_MONOTONIC_RAW, &raw)) {
    101		printf("ERR: NO CLOCK_MONOTONIC_RAW\n");
    102		return -1;
    103	}
    104
    105	tx1.modes = 0;
    106	adjtimex(&tx1);
    107	get_monotonic_and_raw(&mon, &raw);
    108	start = mon;
    109	delta1 = diff_timespec(mon, raw);
    110
    111	if (tx1.offset)
    112		printf("WARNING: ADJ_OFFSET in progress, this will cause inaccurate results\n");
    113
    114	printf("Estimating clock drift: ");
    115	fflush(stdout);
    116	sleep(120);
    117
    118	get_monotonic_and_raw(&mon, &raw);
    119	end = mon;
    120	tx2.modes = 0;
    121	adjtimex(&tx2);
    122	delta2 = diff_timespec(mon, raw);
    123
    124	interval = diff_timespec(start, end);
    125
    126	/* calculate measured ppm between MONOTONIC and MONOTONIC_RAW */
    127	eppm = ((delta2-delta1)*NSEC_PER_SEC)/interval;
    128	eppm = -eppm;
    129	printf("%lld.%i(est)", eppm/1000, abs((int)(eppm%1000)));
    130
    131	/* Avg the two actual freq samples adjtimex gave us */
    132	ppm = (tx1.freq + tx2.freq) * 1000 / 2;
    133	ppm = (long long)tx1.freq * 1000;
    134	ppm = shift_right(ppm, 16);
    135	printf(" %lld.%i(act)", ppm/1000, abs((int)(ppm%1000)));
    136
    137	if (llabs(eppm - ppm) > 1000) {
    138		if (tx1.offset || tx2.offset ||
    139		    tx1.freq != tx2.freq || tx1.tick != tx2.tick) {
    140			printf("	[SKIP]\n");
    141			return ksft_exit_skip("The clock was adjusted externally. Shutdown NTPd or other time sync daemons\n");
    142		}
    143		printf("	[FAILED]\n");
    144		return ksft_exit_fail();
    145	}
    146	printf("	[OK]\n");
    147	return  ksft_exit_pass();
    148}