1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2018 Google, Inc.
3*49cdfc7eSAndroid Build Coastguard Worker *
4*49cdfc7eSAndroid Build Coastguard Worker * SPDX-License-Identifier: GPL-2.0-or-later
5*49cdfc7eSAndroid Build Coastguard Worker */
6*49cdfc7eSAndroid Build Coastguard Worker
7*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
8*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <sched.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
16*49cdfc7eSAndroid Build Coastguard Worker
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_cpu.h"
18*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_file_ops.h"
19*49cdfc7eSAndroid Build Coastguard Worker
20*49cdfc7eSAndroid Build Coastguard Worker #include "util.h"
21*49cdfc7eSAndroid Build Coastguard Worker
affine(int cpu)22*49cdfc7eSAndroid Build Coastguard Worker void affine(int cpu)
23*49cdfc7eSAndroid Build Coastguard Worker {
24*49cdfc7eSAndroid Build Coastguard Worker cpu_set_t cpuset;
25*49cdfc7eSAndroid Build Coastguard Worker CPU_ZERO(&cpuset);
26*49cdfc7eSAndroid Build Coastguard Worker CPU_SET(cpu, &cpuset);
27*49cdfc7eSAndroid Build Coastguard Worker ERROR_CHECK(sched_setaffinity(0, sizeof(cpu_set_t), &cpuset));
28*49cdfc7eSAndroid Build Coastguard Worker }
29*49cdfc7eSAndroid Build Coastguard Worker
30*49cdfc7eSAndroid Build Coastguard Worker /*
31*49cdfc7eSAndroid Build Coastguard Worker * Busywait for a certain amount of wallclock time.
32*49cdfc7eSAndroid Build Coastguard Worker * If sleep is nonzero, sleep for 1ms between each check.
33*49cdfc7eSAndroid Build Coastguard Worker */
burn(unsigned int usec,int sleep)34*49cdfc7eSAndroid Build Coastguard Worker void burn(unsigned int usec, int sleep)
35*49cdfc7eSAndroid Build Coastguard Worker {
36*49cdfc7eSAndroid Build Coastguard Worker unsigned long long now_usec, end_usec;
37*49cdfc7eSAndroid Build Coastguard Worker struct timespec ts;
38*49cdfc7eSAndroid Build Coastguard Worker
39*49cdfc7eSAndroid Build Coastguard Worker if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
40*49cdfc7eSAndroid Build Coastguard Worker printf("clock_gettime() reported an error\n");
41*49cdfc7eSAndroid Build Coastguard Worker return;
42*49cdfc7eSAndroid Build Coastguard Worker }
43*49cdfc7eSAndroid Build Coastguard Worker end_usec = (ts.tv_sec) * USEC_PER_SEC + (ts.tv_nsec / 1000) + usec;
44*49cdfc7eSAndroid Build Coastguard Worker while(1) {
45*49cdfc7eSAndroid Build Coastguard Worker if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
46*49cdfc7eSAndroid Build Coastguard Worker printf("clock_gettime() reported an error\n");
47*49cdfc7eSAndroid Build Coastguard Worker return;
48*49cdfc7eSAndroid Build Coastguard Worker }
49*49cdfc7eSAndroid Build Coastguard Worker now_usec = ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / 1000;
50*49cdfc7eSAndroid Build Coastguard Worker if (now_usec > end_usec)
51*49cdfc7eSAndroid Build Coastguard Worker return;
52*49cdfc7eSAndroid Build Coastguard Worker if (sleep)
53*49cdfc7eSAndroid Build Coastguard Worker usleep(1000);
54*49cdfc7eSAndroid Build Coastguard Worker }
55*49cdfc7eSAndroid Build Coastguard Worker }
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker #define CAP_STATE_FILE_SIZE 1024
read_capacity_sched_domains(int cpu,unsigned int * cap)58*49cdfc7eSAndroid Build Coastguard Worker static int read_capacity_sched_domains(int cpu, unsigned int *cap)
59*49cdfc7eSAndroid Build Coastguard Worker {
60*49cdfc7eSAndroid Build Coastguard Worker char *filebuf, *tmp1, *tmp2;
61*49cdfc7eSAndroid Build Coastguard Worker char cap_states_file[100];
62*49cdfc7eSAndroid Build Coastguard Worker int cap_states_fd;
63*49cdfc7eSAndroid Build Coastguard Worker int bytes, rv;
64*49cdfc7eSAndroid Build Coastguard Worker
65*49cdfc7eSAndroid Build Coastguard Worker sprintf(cap_states_file,
66*49cdfc7eSAndroid Build Coastguard Worker "/proc/sys/kernel/sched_domain/cpu%d/domain0/group0/energy/cap_states",
67*49cdfc7eSAndroid Build Coastguard Worker cpu);
68*49cdfc7eSAndroid Build Coastguard Worker cap_states_fd = open(cap_states_file, O_RDONLY);
69*49cdfc7eSAndroid Build Coastguard Worker if (cap_states_fd == -1)
70*49cdfc7eSAndroid Build Coastguard Worker return -ENOENT;
71*49cdfc7eSAndroid Build Coastguard Worker
72*49cdfc7eSAndroid Build Coastguard Worker bytes = CAP_STATE_FILE_SIZE;
73*49cdfc7eSAndroid Build Coastguard Worker filebuf = calloc(1, CAP_STATE_FILE_SIZE + 1);
74*49cdfc7eSAndroid Build Coastguard Worker if (!filebuf) {
75*49cdfc7eSAndroid Build Coastguard Worker printf("Failed to calloc buffer for cap_states\n");
76*49cdfc7eSAndroid Build Coastguard Worker return -1;
77*49cdfc7eSAndroid Build Coastguard Worker }
78*49cdfc7eSAndroid Build Coastguard Worker tmp1 = filebuf;
79*49cdfc7eSAndroid Build Coastguard Worker while (bytes) {
80*49cdfc7eSAndroid Build Coastguard Worker rv = read(cap_states_fd, tmp1, bytes);
81*49cdfc7eSAndroid Build Coastguard Worker if (rv == -1) {
82*49cdfc7eSAndroid Build Coastguard Worker printf("Could not read cap_states\n");
83*49cdfc7eSAndroid Build Coastguard Worker return -1;
84*49cdfc7eSAndroid Build Coastguard Worker }
85*49cdfc7eSAndroid Build Coastguard Worker if (rv == 0)
86*49cdfc7eSAndroid Build Coastguard Worker break;
87*49cdfc7eSAndroid Build Coastguard Worker tmp1 += rv;
88*49cdfc7eSAndroid Build Coastguard Worker bytes -= rv;
89*49cdfc7eSAndroid Build Coastguard Worker }
90*49cdfc7eSAndroid Build Coastguard Worker if (tmp1 - filebuf == CAP_STATE_FILE_SIZE) {
91*49cdfc7eSAndroid Build Coastguard Worker printf("CAP_STATE_FILE_SIZE exhausted, increase\n");
92*49cdfc7eSAndroid Build Coastguard Worker return -1;
93*49cdfc7eSAndroid Build Coastguard Worker }
94*49cdfc7eSAndroid Build Coastguard Worker tmp1 = strrchr(filebuf, '\t');
95*49cdfc7eSAndroid Build Coastguard Worker if (!tmp1 || tmp1 == filebuf ) {
96*49cdfc7eSAndroid Build Coastguard Worker printf("Malformatted cap_states_file (1).\n%s\n", filebuf);
97*49cdfc7eSAndroid Build Coastguard Worker return -1;
98*49cdfc7eSAndroid Build Coastguard Worker }
99*49cdfc7eSAndroid Build Coastguard Worker tmp1 = strrchr(tmp1 - 1, '\t');
100*49cdfc7eSAndroid Build Coastguard Worker if (!tmp1 || tmp1 == filebuf) {
101*49cdfc7eSAndroid Build Coastguard Worker printf("Malformatted cap_states_file (2).\n%s\n", filebuf);
102*49cdfc7eSAndroid Build Coastguard Worker return -1;
103*49cdfc7eSAndroid Build Coastguard Worker }
104*49cdfc7eSAndroid Build Coastguard Worker tmp1 = strrchr(tmp1 - 1, '\t');
105*49cdfc7eSAndroid Build Coastguard Worker if (!tmp1 || tmp1 == filebuf) {
106*49cdfc7eSAndroid Build Coastguard Worker printf("Malformatted cap_states_file (3).\n%s\n", filebuf);
107*49cdfc7eSAndroid Build Coastguard Worker return -1;
108*49cdfc7eSAndroid Build Coastguard Worker }
109*49cdfc7eSAndroid Build Coastguard Worker /* tmp1 now points to tab after the capacity we want. */
110*49cdfc7eSAndroid Build Coastguard Worker *tmp1 = 0;
111*49cdfc7eSAndroid Build Coastguard Worker tmp2 = strrchr(tmp1 - 1, '\t');
112*49cdfc7eSAndroid Build Coastguard Worker if (!tmp2)
113*49cdfc7eSAndroid Build Coastguard Worker tmp2 = filebuf;
114*49cdfc7eSAndroid Build Coastguard Worker else
115*49cdfc7eSAndroid Build Coastguard Worker tmp2++;
116*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(tmp2,"%d", cap) != 1) {
117*49cdfc7eSAndroid Build Coastguard Worker printf("Failed to parse capacity from cap_states.\n");
118*49cdfc7eSAndroid Build Coastguard Worker return -1;
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker free(filebuf);
121*49cdfc7eSAndroid Build Coastguard Worker if (close(cap_states_fd)) {
122*49cdfc7eSAndroid Build Coastguard Worker printf("Failed to close cap_states file.\n");
123*49cdfc7eSAndroid Build Coastguard Worker return -1;
124*49cdfc7eSAndroid Build Coastguard Worker }
125*49cdfc7eSAndroid Build Coastguard Worker
126*49cdfc7eSAndroid Build Coastguard Worker return 0;
127*49cdfc7eSAndroid Build Coastguard Worker }
128*49cdfc7eSAndroid Build Coastguard Worker
read_capacity_sysfs(int cpu,unsigned int * cap)129*49cdfc7eSAndroid Build Coastguard Worker static int read_capacity_sysfs(int cpu, unsigned int *cap)
130*49cdfc7eSAndroid Build Coastguard Worker {
131*49cdfc7eSAndroid Build Coastguard Worker char path[100];
132*49cdfc7eSAndroid Build Coastguard Worker
133*49cdfc7eSAndroid Build Coastguard Worker sprintf(path, "/sys/devices/system/cpu/cpu%d/cpu_capacity", cpu);
134*49cdfc7eSAndroid Build Coastguard Worker
135*49cdfc7eSAndroid Build Coastguard Worker return SAFE_FILE_LINES_SCANF(path, "%u", cap);
136*49cdfc7eSAndroid Build Coastguard Worker }
137*49cdfc7eSAndroid Build Coastguard Worker
read_cpu_capacity(int cpu,unsigned int * cap)138*49cdfc7eSAndroid Build Coastguard Worker static int read_cpu_capacity(int cpu, unsigned int *cap)
139*49cdfc7eSAndroid Build Coastguard Worker {
140*49cdfc7eSAndroid Build Coastguard Worker int ret = read_capacity_sched_domains(cpu, cap);
141*49cdfc7eSAndroid Build Coastguard Worker
142*49cdfc7eSAndroid Build Coastguard Worker /*
143*49cdfc7eSAndroid Build Coastguard Worker * Capacities are exposed in sched debug for android 4.9 and older.
144*49cdfc7eSAndroid Build Coastguard Worker * Otherwise, upstream uses a sysfs interface.
145*49cdfc7eSAndroid Build Coastguard Worker */
146*49cdfc7eSAndroid Build Coastguard Worker if (ret == -ENOENT)
147*49cdfc7eSAndroid Build Coastguard Worker ret = read_capacity_sysfs(cpu, cap);
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker if (ret)
150*49cdfc7eSAndroid Build Coastguard Worker perror(NULL);
151*49cdfc7eSAndroid Build Coastguard Worker
152*49cdfc7eSAndroid Build Coastguard Worker return ret;
153*49cdfc7eSAndroid Build Coastguard Worker }
154*49cdfc7eSAndroid Build Coastguard Worker
155*49cdfc7eSAndroid Build Coastguard Worker /*
156*49cdfc7eSAndroid Build Coastguard Worker * get_bigs = 0, search for smallest CPUs
157*49cdfc7eSAndroid Build Coastguard Worker * get_bigs = 1, search for CPUs other than the smallest CPUs
158*49cdfc7eSAndroid Build Coastguard Worker */
find_cpus_with_capacity(int get_bigs,cpu_set_t * cpuset)159*49cdfc7eSAndroid Build Coastguard Worker int find_cpus_with_capacity(int get_bigs, cpu_set_t *cpuset)
160*49cdfc7eSAndroid Build Coastguard Worker {
161*49cdfc7eSAndroid Build Coastguard Worker unsigned int cap, smallest = -1;
162*49cdfc7eSAndroid Build Coastguard Worker int i;
163*49cdfc7eSAndroid Build Coastguard Worker
164*49cdfc7eSAndroid Build Coastguard Worker CPU_ZERO(cpuset);
165*49cdfc7eSAndroid Build Coastguard Worker
166*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < tst_ncpus(); i++) {
167*49cdfc7eSAndroid Build Coastguard Worker if (read_cpu_capacity(i, &cap))
168*49cdfc7eSAndroid Build Coastguard Worker return -1;
169*49cdfc7eSAndroid Build Coastguard Worker
170*49cdfc7eSAndroid Build Coastguard Worker if (cap < smallest) {
171*49cdfc7eSAndroid Build Coastguard Worker smallest = cap;
172*49cdfc7eSAndroid Build Coastguard Worker CPU_ZERO(cpuset);
173*49cdfc7eSAndroid Build Coastguard Worker CPU_SET(i, cpuset);
174*49cdfc7eSAndroid Build Coastguard Worker } else if (cap == smallest) {
175*49cdfc7eSAndroid Build Coastguard Worker CPU_SET(i, cpuset);
176*49cdfc7eSAndroid Build Coastguard Worker }
177*49cdfc7eSAndroid Build Coastguard Worker }
178*49cdfc7eSAndroid Build Coastguard Worker
179*49cdfc7eSAndroid Build Coastguard Worker if (!get_bigs)
180*49cdfc7eSAndroid Build Coastguard Worker return 0;
181*49cdfc7eSAndroid Build Coastguard Worker
182*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < tst_ncpus(); i++)
183*49cdfc7eSAndroid Build Coastguard Worker if (CPU_ISSET(i, cpuset))
184*49cdfc7eSAndroid Build Coastguard Worker CPU_CLR(i, cpuset);
185*49cdfc7eSAndroid Build Coastguard Worker else
186*49cdfc7eSAndroid Build Coastguard Worker CPU_SET(i, cpuset);
187*49cdfc7eSAndroid Build Coastguard Worker
188*49cdfc7eSAndroid Build Coastguard Worker return 0;
189*49cdfc7eSAndroid Build Coastguard Worker }
190*49cdfc7eSAndroid Build Coastguard Worker
191