14007Sjoerg// SPDX-License-Identifier: GPL-2.0 24007Sjoerg#include <math.h> 34007Sjoerg#include <unistd.h> 44007Sjoerg#include <stdio.h> 54007Sjoerg#include <stdlib.h> 64007Sjoerg#include <sys/types.h> 74007Sjoerg#include <sys/stat.h> 84007Sjoerg#include <fcntl.h> 94007Sjoerg#include <sys/timeb.h> 104007Sjoerg#include <sched.h> 114007Sjoerg#include <errno.h> 124007Sjoerg#include <string.h> 134007Sjoerg#include <time.h> 144007Sjoerg#include "../kselftest.h" 154007Sjoerg 164007Sjoerg#define MSEC_PER_SEC 1000L 174007Sjoerg#define NSEC_PER_MSEC 1000000L 184007Sjoerg 194007Sjoergvoid usage(char *name) { 204007Sjoerg printf ("Usage: %s cpunum\n", name); 214007Sjoerg} 224007Sjoerg 234007Sjoergint main(int argc, char **argv) { 244007Sjoerg unsigned int i, cpu, fd; 254007Sjoerg char msr_file_name[64]; 264007Sjoerg long long tsc, old_tsc, new_tsc; 274007Sjoerg long long aperf, old_aperf, new_aperf; 284007Sjoerg long long mperf, old_mperf, new_mperf; 294007Sjoerg struct timespec before, after; 304007Sjoerg long long int start, finish, total; 314007Sjoerg cpu_set_t cpuset; 324007Sjoerg 334007Sjoerg if (argc != 2) { 344007Sjoerg usage(argv[0]); 354007Sjoerg return 1; 364007Sjoerg } 374007Sjoerg 384007Sjoerg errno = 0; 394007Sjoerg cpu = strtol(argv[1], (char **) NULL, 10); 404007Sjoerg 414007Sjoerg if (errno) { 424007Sjoerg usage(argv[0]); 434007Sjoerg return 1; 444007Sjoerg } 454007Sjoerg 464007Sjoerg sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu); 474007Sjoerg fd = open(msr_file_name, O_RDONLY); 484007Sjoerg 494007Sjoerg if (fd == -1) { 504007Sjoerg printf("/dev/cpu/%d/msr: %s\n", cpu, strerror(errno)); 514007Sjoerg return KSFT_SKIP; 524007Sjoerg } 534007Sjoerg 544007Sjoerg CPU_ZERO(&cpuset); 554007Sjoerg CPU_SET(cpu, &cpuset); 564007Sjoerg 574007Sjoerg if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) { 584007Sjoerg perror("Failed to set cpu affinity"); 594007Sjoerg return 1; 604007Sjoerg } 614007Sjoerg 624007Sjoerg if (clock_gettime(CLOCK_MONOTONIC, &before) < 0) { 634007Sjoerg perror("clock_gettime"); 644007Sjoerg return 1; 654007Sjoerg } 664007Sjoerg pread(fd, &old_tsc, sizeof(old_tsc), 0x10); 674007Sjoerg pread(fd, &old_aperf, sizeof(old_mperf), 0xe7); 684007Sjoerg pread(fd, &old_mperf, sizeof(old_aperf), 0xe8); 694007Sjoerg 704007Sjoerg for (i=0; i<0x8fffffff; i++) { 714007Sjoerg sqrt(i); 724007Sjoerg } 734007Sjoerg 744007Sjoerg if (clock_gettime(CLOCK_MONOTONIC, &after) < 0) { 754007Sjoerg perror("clock_gettime"); 764007Sjoerg return 1; 774007Sjoerg } 784007Sjoerg pread(fd, &new_tsc, sizeof(new_tsc), 0x10); 794007Sjoerg pread(fd, &new_aperf, sizeof(new_mperf), 0xe7); 804007Sjoerg pread(fd, &new_mperf, sizeof(new_aperf), 0xe8); 814007Sjoerg 824007Sjoerg tsc = new_tsc-old_tsc; 834007Sjoerg aperf = new_aperf-old_aperf; 844007Sjoerg mperf = new_mperf-old_mperf; 854007Sjoerg 864007Sjoerg start = before.tv_sec*MSEC_PER_SEC + before.tv_nsec/NSEC_PER_MSEC; 874007Sjoerg finish = after.tv_sec*MSEC_PER_SEC + after.tv_nsec/NSEC_PER_MSEC; 884007Sjoerg total = finish - start; 894007Sjoerg 904007Sjoerg printf("runTime: %4.2f\n", 1.0*total/MSEC_PER_SEC); 914007Sjoerg printf("freq: %7.0f\n", tsc / (1.0*aperf / (1.0 * mperf)) / total); 924007Sjoerg return 0; 934007Sjoerg} 944007Sjoerg