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

alarmtimer-suspend.c (4397B)


      1/* alarmtimer suspend test
      2 *		John Stultz (john.stultz@linaro.org)
      3 *              (C) Copyright Linaro 2013
      4 *              Licensed under the GPLv2
      5 *
      6 *   This test makes sure the alarmtimer & RTC wakeup code is
      7 *   functioning.
      8 *
      9 *  To build:
     10 *	$ gcc alarmtimer-suspend.c -o alarmtimer-suspend -lrt
     11 *
     12 *   This program is free software: you can redistribute it and/or modify
     13 *   it under the terms of the GNU General Public License as published by
     14 *   the Free Software Foundation, either version 2 of the License, or
     15 *   (at your option) any later version.
     16 *
     17 *   This program is distributed in the hope that it will be useful,
     18 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     19 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20 *   GNU General Public License for more details.
     21 */
     22
     23
     24#include <stdio.h>
     25#include <unistd.h>
     26#include <time.h>
     27#include <string.h>
     28#include <signal.h>
     29#include <stdlib.h>
     30#include <pthread.h>
     31#include "../kselftest.h"
     32
     33#define CLOCK_REALTIME			0
     34#define CLOCK_MONOTONIC			1
     35#define CLOCK_PROCESS_CPUTIME_ID	2
     36#define CLOCK_THREAD_CPUTIME_ID		3
     37#define CLOCK_MONOTONIC_RAW		4
     38#define CLOCK_REALTIME_COARSE		5
     39#define CLOCK_MONOTONIC_COARSE		6
     40#define CLOCK_BOOTTIME			7
     41#define CLOCK_REALTIME_ALARM		8
     42#define CLOCK_BOOTTIME_ALARM		9
     43#define CLOCK_HWSPECIFIC		10
     44#define CLOCK_TAI			11
     45#define NR_CLOCKIDS			12
     46
     47
     48#define NSEC_PER_SEC 1000000000ULL
     49#define UNREASONABLE_LAT (NSEC_PER_SEC * 5) /* hopefully we resume in 5 secs */
     50
     51#define SUSPEND_SECS 15
     52int alarmcount;
     53int alarm_clock_id;
     54struct timespec start_time;
     55
     56
     57char *clockstring(int clockid)
     58{
     59	switch (clockid) {
     60	case CLOCK_REALTIME:
     61		return "CLOCK_REALTIME";
     62	case CLOCK_MONOTONIC:
     63		return "CLOCK_MONOTONIC";
     64	case CLOCK_PROCESS_CPUTIME_ID:
     65		return "CLOCK_PROCESS_CPUTIME_ID";
     66	case CLOCK_THREAD_CPUTIME_ID:
     67		return "CLOCK_THREAD_CPUTIME_ID";
     68	case CLOCK_MONOTONIC_RAW:
     69		return "CLOCK_MONOTONIC_RAW";
     70	case CLOCK_REALTIME_COARSE:
     71		return "CLOCK_REALTIME_COARSE";
     72	case CLOCK_MONOTONIC_COARSE:
     73		return "CLOCK_MONOTONIC_COARSE";
     74	case CLOCK_BOOTTIME:
     75		return "CLOCK_BOOTTIME";
     76	case CLOCK_REALTIME_ALARM:
     77		return "CLOCK_REALTIME_ALARM";
     78	case CLOCK_BOOTTIME_ALARM:
     79		return "CLOCK_BOOTTIME_ALARM";
     80	case CLOCK_TAI:
     81		return "CLOCK_TAI";
     82	}
     83	return "UNKNOWN_CLOCKID";
     84}
     85
     86
     87long long timespec_sub(struct timespec a, struct timespec b)
     88{
     89	long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
     90
     91	ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
     92	return ret;
     93}
     94
     95int final_ret = 0;
     96
     97void sigalarm(int signo)
     98{
     99	long long delta_ns;
    100	struct timespec ts;
    101
    102	clock_gettime(alarm_clock_id, &ts);
    103	alarmcount++;
    104
    105	delta_ns = timespec_sub(start_time, ts);
    106	delta_ns -= NSEC_PER_SEC * SUSPEND_SECS * alarmcount;
    107
    108	printf("ALARM(%i): %ld:%ld latency: %lld ns ", alarmcount, ts.tv_sec,
    109							ts.tv_nsec, delta_ns);
    110
    111	if (delta_ns > UNREASONABLE_LAT) {
    112		printf("[FAIL]\n");
    113		final_ret = -1;
    114	} else
    115		printf("[OK]\n");
    116
    117}
    118
    119int main(void)
    120{
    121	timer_t tm1;
    122	struct itimerspec its1, its2;
    123	struct sigevent se;
    124	struct sigaction act;
    125	int signum = SIGRTMAX;
    126
    127	/* Set up signal handler: */
    128	sigfillset(&act.sa_mask);
    129	act.sa_flags = 0;
    130	act.sa_handler = sigalarm;
    131	sigaction(signum, &act, NULL);
    132
    133	/* Set up timer: */
    134	memset(&se, 0, sizeof(se));
    135	se.sigev_notify = SIGEV_SIGNAL;
    136	se.sigev_signo = signum;
    137	se.sigev_value.sival_int = 0;
    138
    139	for (alarm_clock_id = CLOCK_REALTIME_ALARM;
    140			alarm_clock_id <= CLOCK_BOOTTIME_ALARM;
    141			alarm_clock_id++) {
    142
    143		alarmcount = 0;
    144		if (timer_create(alarm_clock_id, &se, &tm1) == -1) {
    145			printf("timer_create failed, %s unsupported?\n",
    146					clockstring(alarm_clock_id));
    147			break;
    148		}
    149
    150		clock_gettime(alarm_clock_id, &start_time);
    151		printf("Start time (%s): %ld:%ld\n", clockstring(alarm_clock_id),
    152				start_time.tv_sec, start_time.tv_nsec);
    153		printf("Setting alarm for every %i seconds\n", SUSPEND_SECS);
    154		its1.it_value = start_time;
    155		its1.it_value.tv_sec += SUSPEND_SECS;
    156		its1.it_interval.tv_sec = SUSPEND_SECS;
    157		its1.it_interval.tv_nsec = 0;
    158
    159		timer_settime(tm1, TIMER_ABSTIME, &its1, &its2);
    160
    161		while (alarmcount < 5)
    162			sleep(1); /* First 5 alarms, do nothing */
    163
    164		printf("Starting suspend loops\n");
    165		while (alarmcount < 10) {
    166			int ret;
    167
    168			sleep(3);
    169			ret = system("echo mem > /sys/power/state");
    170			if (ret)
    171				break;
    172		}
    173		timer_delete(tm1);
    174	}
    175	if (final_ret)
    176		return ksft_exit_fail();
    177	return ksft_exit_pass();
    178}