1 // SPDX-License-Identifier: GPL-2.0 2 #include <math.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <fcntl.h> 9 #include <sys/timeb.h> 10 #include <sched.h> 11 #include <errno.h> 12 #include <string.h> 13 #include <time.h> 14 #include "../kselftest.h" 15 16 #define MSEC_PER_SEC 1000L 17 #define NSEC_PER_MSEC 1000000L 18 19 void usage(char *name) { 20 printf ("Usage: %s cpunum\n", name); 21 } 22 23 int main(int argc, char **argv) { 24 unsigned int i, cpu, fd; 25 char msr_file_name[64]; 26 long long tsc, old_tsc, new_tsc; 27 long long aperf, old_aperf, new_aperf; 28 long long mperf, old_mperf, new_mperf; 29 struct timespec before, after; 30 long long int start, finish, total; 31 cpu_set_t cpuset; 32 33 if (argc != 2) { 34 usage(argv[0]); 35 return 1; 36 } 37 38 errno = 0; 39 cpu = strtol(argv[1], (char **) NULL, 10); 40 41 if (errno) { 42 usage(argv[0]); 43 return 1; 44 } 45 46 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu); 47 fd = open(msr_file_name, O_RDONLY); 48 49 if (fd == -1) { 50 printf("/dev/cpu/%d/msr: %s\n", cpu, strerror(errno)); 51 return KSFT_SKIP; 52 } 53 54 CPU_ZERO(&cpuset); 55 CPU_SET(cpu, &cpuset); 56 57 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) { 58 perror("Failed to set cpu affinity"); 59 return 1; 60 } 61 62 if (clock_gettime(CLOCK_MONOTONIC, &before) < 0) { 63 perror("clock_gettime"); 64 return 1; 65 } 66 pread(fd, &old_tsc, sizeof(old_tsc), 0x10); 67 pread(fd, &old_aperf, sizeof(old_mperf), 0xe7); 68 pread(fd, &old_mperf, sizeof(old_aperf), 0xe8); 69 70 for (i=0; i<0x8fffffff; i++) { 71 sqrt(i); 72 } 73 74 if (clock_gettime(CLOCK_MONOTONIC, &after) < 0) { 75 perror("clock_gettime"); 76 return 1; 77 } 78 pread(fd, &new_tsc, sizeof(new_tsc), 0x10); 79 pread(fd, &new_aperf, sizeof(new_mperf), 0xe7); 80 pread(fd, &new_mperf, sizeof(new_aperf), 0xe8); 81 82 tsc = new_tsc-old_tsc; 83 aperf = new_aperf-old_aperf; 84 mperf = new_mperf-old_mperf; 85 86 start = before.tv_sec*MSEC_PER_SEC + before.tv_nsec/NSEC_PER_MSEC; 87 finish = after.tv_sec*MSEC_PER_SEC + after.tv_nsec/NSEC_PER_MSEC; 88 total = finish - start; 89 90 printf("runTime: %4.2f\n", 1.0*total/MSEC_PER_SEC); 91 printf("freq: %7.0f\n", tsc / (1.0*aperf / (1.0 * mperf)) / total); 92 return 0; 93 } 94