1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) 2013-2014 Oracle and/or its affiliates. All Rights Reserved. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or 5f08c3bdfSopenharmony_ci * modify it under the terms of the GNU General Public License as 6f08c3bdfSopenharmony_ci * published by the Free Software Foundation; either version 2 of 7f08c3bdfSopenharmony_ci * the License, or (at your option) any later version. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, 10f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12f08c3bdfSopenharmony_ci * GNU General Public License for more details. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 15f08c3bdfSopenharmony_ci * along with this program; if not, write the Free Software Foundation, 16f08c3bdfSopenharmony_ci * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * Author: Alexey Kodanev <alexey.kodanev@oracle.com> 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * Check support for disabling dynamic overclocking in acpi_cpufreq driver. 21f08c3bdfSopenharmony_ci * Required Linux 3.7+. 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * The test compares time spent on sum calculation with/without 24f08c3bdfSopenharmony_ci * boost-disable bit. If boost is enabled we can get a slightly shorter 25f08c3bdfSopenharmony_ci * time period. Measure elapsed time instead of sysfs cpuinfo_cur_freq value, 26f08c3bdfSopenharmony_ci * because after the upstream commit 8673b83bf2f013379453b4779047bf3c6ae387e4, 27f08c3bdfSopenharmony_ci * current cpu frequency became target cpu frequency. 28f08c3bdfSopenharmony_ci */ 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#define _GNU_SOURCE 31f08c3bdfSopenharmony_ci#include <errno.h> 32f08c3bdfSopenharmony_ci#include <sched.h> 33f08c3bdfSopenharmony_ci#include <time.h> 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#include "test.h" 36f08c3bdfSopenharmony_ci#include "lapi/posix_clocks.h" 37f08c3bdfSopenharmony_ci#include "safe_macros.h" 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cichar *TCID = "cpufreq_boost"; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci#define SYSFS_CPU_DIR "/sys/devices/system/cpu/" 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistruct cpufreq_driver_info { 44f08c3bdfSopenharmony_ci char *name; 45f08c3bdfSopenharmony_ci int off; 46f08c3bdfSopenharmony_ci char *on_str; 47f08c3bdfSopenharmony_ci char *off_str; 48f08c3bdfSopenharmony_ci char *file; 49f08c3bdfSopenharmony_ci}; 50f08c3bdfSopenharmony_cistatic const struct cpufreq_driver_info cdrv[] = { 51f08c3bdfSopenharmony_ci { "acpi_cpufreq", 0, "1", "0", SYSFS_CPU_DIR "cpufreq/boost" }, 52f08c3bdfSopenharmony_ci { "intel_pstate", 1, "0", "1", SYSFS_CPU_DIR "intel_pstate/no_turbo" }, 53f08c3bdfSopenharmony_ci}; 54f08c3bdfSopenharmony_cistatic int id = -1; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistatic int boost_value; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ciconst char governor[] = SYSFS_CPU_DIR "cpu0/cpufreq/scaling_governor"; 59f08c3bdfSopenharmony_cistatic char governor_name[16]; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ciconst char maxspeed[] = SYSFS_CPU_DIR "cpu0/cpufreq/scaling_max_freq"; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic void check_set_turbo(char *file, char *off) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci int fd; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci fd = SAFE_OPEN(NULL, file, O_WRONLY); 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci /* We try to skip test when getting EPERM. */ 70f08c3bdfSopenharmony_ci if (write(fd, off, 1) == -1 && errno == EPERM) { 71f08c3bdfSopenharmony_ci SAFE_CLOSE(NULL, fd); 72f08c3bdfSopenharmony_ci tst_brkm(TCONF, NULL, 73f08c3bdfSopenharmony_ci "Turbo is disabled by BIOS or unavailable on processor"); 74f08c3bdfSopenharmony_ci } 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci SAFE_CLOSE(NULL, fd); 77f08c3bdfSopenharmony_ci} 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_cistatic void cleanup(void) 80f08c3bdfSopenharmony_ci{ 81f08c3bdfSopenharmony_ci FILE_PRINTF(cdrv[id].file, "%d", boost_value); 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci if (governor[0] != '\0') 84f08c3bdfSopenharmony_ci FILE_PRINTF(governor, "%s", governor_name); 85f08c3bdfSopenharmony_ci} 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_cistatic void setup(void) 88f08c3bdfSopenharmony_ci{ 89f08c3bdfSopenharmony_ci int fd; 90f08c3bdfSopenharmony_ci unsigned int i; 91f08c3bdfSopenharmony_ci tst_require_root(); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci if (tst_is_virt(VIRT_ANY)) 94f08c3bdfSopenharmony_ci tst_brkm(TCONF, NULL, "running in a virtual machine, overclock not reliably measureable"); 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(cdrv); ++i) { 97f08c3bdfSopenharmony_ci fd = open(cdrv[i].file, O_RDWR); 98f08c3bdfSopenharmony_ci if (fd == -1) 99f08c3bdfSopenharmony_ci continue; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci id = i; 102f08c3bdfSopenharmony_ci close(fd); 103f08c3bdfSopenharmony_ci break; 104f08c3bdfSopenharmony_ci } 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci if (id == -1) 107f08c3bdfSopenharmony_ci tst_brkm(TCONF, NULL, "overclock not supported"); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci tst_resm(TINFO, "found '%s' driver, sysfs knob '%s'", 110f08c3bdfSopenharmony_ci cdrv[id].name, cdrv[id].file); 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(NULL, cdrv[i].file, "%d", &boost_value); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci /* For intel_pstate, we cannot write data into intel_pstate/no_turbo 117f08c3bdfSopenharmony_ci * and return EPERM if turbo is disabled by BIOS or unavailable on 118f08c3bdfSopenharmony_ci * processor. We should check this case by writing original data. 119f08c3bdfSopenharmony_ci */ 120f08c3bdfSopenharmony_ci if (!strcmp(cdrv[i].name, "intel_pstate") && boost_value == cdrv[i].off) 121f08c3bdfSopenharmony_ci check_set_turbo(cdrv[i].file, cdrv[i].off_str); 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci /* change cpu0 scaling governor */ 124f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(NULL, governor, "%s", governor_name); 125f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(cleanup, governor, "%s", "performance"); 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci /* use only cpu0 */ 128f08c3bdfSopenharmony_ci cpu_set_t set; 129f08c3bdfSopenharmony_ci CPU_ZERO(&set); 130f08c3bdfSopenharmony_ci CPU_SET(0, &set); 131f08c3bdfSopenharmony_ci if (sched_setaffinity(0, sizeof(cpu_set_t), &set) < 0) 132f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "failed to set CPU0"); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci struct sched_param params; 135f08c3bdfSopenharmony_ci params.sched_priority = sched_get_priority_max(SCHED_FIFO); 136f08c3bdfSopenharmony_ci if (sched_setscheduler(getpid(), SCHED_FIFO, ¶ms)) { 137f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, 138f08c3bdfSopenharmony_ci "failed to set FIFO sched with max priority"); 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci} 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_cistatic int load_cpu(int max_freq_khz) 143f08c3bdfSopenharmony_ci{ 144f08c3bdfSopenharmony_ci int sum = 0, i = 0, total_time_ms; 145f08c3bdfSopenharmony_ci struct timespec tv_start, tv_end; 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci const int max_sum = max_freq_khz / 1000; 148f08c3bdfSopenharmony_ci const int units = 1000000; /* Mhz */ 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci clock_gettime(CLOCK_MONOTONIC_RAW, &tv_start); 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci do { 153f08c3bdfSopenharmony_ci for (i = 0; i < units; ++i) 154f08c3bdfSopenharmony_ci asm ("" : : : "memory"); 155f08c3bdfSopenharmony_ci } while (++sum < max_sum); 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci clock_gettime(CLOCK_MONOTONIC_RAW, &tv_end); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci total_time_ms = (tv_end.tv_sec - tv_start.tv_sec) * 1000 + 160f08c3bdfSopenharmony_ci (tv_end.tv_nsec - tv_start.tv_nsec) / 1000000; 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci if (!total_time_ms) 163f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "time period is 0"); 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci tst_resm(TINFO, "elapsed time is %d ms", total_time_ms); 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci return total_time_ms; 168f08c3bdfSopenharmony_ci} 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_cistatic void test_run(void) 171f08c3bdfSopenharmony_ci{ 172f08c3bdfSopenharmony_ci int boost_time, boost_off_time, max_freq_khz; 173f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(cleanup, maxspeed, "%d", &max_freq_khz); 174f08c3bdfSopenharmony_ci tst_resm(TINFO, "maximum speed is %d KHz", max_freq_khz); 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci /* Enable boost */ 177f08c3bdfSopenharmony_ci if (boost_value == cdrv[id].off) 178f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(cleanup, cdrv[id].file, "%s", cdrv[id].on_str); 179f08c3bdfSopenharmony_ci tst_resm(TINFO, "load CPU0 with boost enabled"); 180f08c3bdfSopenharmony_ci boost_time = load_cpu(max_freq_khz); 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_ci /* Disable boost */ 183f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(cleanup, cdrv[id].file, "%s", cdrv[id].off_str); 184f08c3bdfSopenharmony_ci tst_resm(TINFO, "load CPU0 with boost disabled"); 185f08c3bdfSopenharmony_ci boost_off_time = load_cpu(max_freq_khz); 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci boost_off_time *= .98; 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_ci tst_resm((boost_time < boost_off_time) ? TPASS : TFAIL, 190f08c3bdfSopenharmony_ci "compare time spent with and without boost (-2%%)"); 191f08c3bdfSopenharmony_ci} 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 194f08c3bdfSopenharmony_ci{ 195f08c3bdfSopenharmony_ci tst_parse_opts(argc, argv, NULL, NULL); 196f08c3bdfSopenharmony_ci 197f08c3bdfSopenharmony_ci setup(); 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci test_run(); 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ci cleanup(); 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci tst_exit(); 204f08c3bdfSopenharmony_ci} 205