18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <unistd.h>
88c2ecf20Sopenharmony_ci#include <stdio.h>
98c2ecf20Sopenharmony_ci#include <stdlib.h>
108c2ecf20Sopenharmony_ci#include <errno.h>
118c2ecf20Sopenharmony_ci#include <string.h>
128c2ecf20Sopenharmony_ci#include <getopt.h>
138c2ecf20Sopenharmony_ci#include <sys/utsname.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "helpers/helpers.h"
168c2ecf20Sopenharmony_ci#include "helpers/sysfs.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic struct option set_opts[] = {
198c2ecf20Sopenharmony_ci     {"perf-bias", optional_argument, NULL, 'b'},
208c2ecf20Sopenharmony_ci     { },
218c2ecf20Sopenharmony_ci};
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic void print_wrong_arg_exit(void)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	printf(_("invalid or unknown argument\n"));
268c2ecf20Sopenharmony_ci	exit(EXIT_FAILURE);
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciint cmd_info(int argc, char **argv)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	extern char *optarg;
328c2ecf20Sopenharmony_ci	extern int optind, opterr, optopt;
338c2ecf20Sopenharmony_ci	unsigned int cpu;
348c2ecf20Sopenharmony_ci	struct utsname uts;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	union {
378c2ecf20Sopenharmony_ci		struct {
388c2ecf20Sopenharmony_ci			int perf_bias:1;
398c2ecf20Sopenharmony_ci		};
408c2ecf20Sopenharmony_ci		int params;
418c2ecf20Sopenharmony_ci	} params = {};
428c2ecf20Sopenharmony_ci	int ret = 0;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	ret = uname(&uts);
458c2ecf20Sopenharmony_ci	if (!ret && (!strcmp(uts.machine, "ppc64le") ||
468c2ecf20Sopenharmony_ci		     !strcmp(uts.machine, "ppc64"))) {
478c2ecf20Sopenharmony_ci		fprintf(stderr, _("Subcommand not supported on POWER.\n"));
488c2ecf20Sopenharmony_ci		return ret;
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	setlocale(LC_ALL, "");
528c2ecf20Sopenharmony_ci	textdomain(PACKAGE);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	/* parameter parsing */
558c2ecf20Sopenharmony_ci	while ((ret = getopt_long(argc, argv, "b", set_opts, NULL)) != -1) {
568c2ecf20Sopenharmony_ci		switch (ret) {
578c2ecf20Sopenharmony_ci		case 'b':
588c2ecf20Sopenharmony_ci			if (params.perf_bias)
598c2ecf20Sopenharmony_ci				print_wrong_arg_exit();
608c2ecf20Sopenharmony_ci			params.perf_bias = 1;
618c2ecf20Sopenharmony_ci			break;
628c2ecf20Sopenharmony_ci		default:
638c2ecf20Sopenharmony_ci			print_wrong_arg_exit();
648c2ecf20Sopenharmony_ci		}
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	if (!params.params)
688c2ecf20Sopenharmony_ci		params.params = 0x7;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* Default is: show output of CPU 0 only */
718c2ecf20Sopenharmony_ci	if (bitmask_isallclear(cpus_chosen))
728c2ecf20Sopenharmony_ci		bitmask_setbit(cpus_chosen, 0);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* Add more per cpu options here */
758c2ecf20Sopenharmony_ci	if (!params.perf_bias)
768c2ecf20Sopenharmony_ci		return ret;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (params.perf_bias) {
798c2ecf20Sopenharmony_ci		if (!run_as_root) {
808c2ecf20Sopenharmony_ci			params.perf_bias = 0;
818c2ecf20Sopenharmony_ci			printf(_("Intel's performance bias setting needs root privileges\n"));
828c2ecf20Sopenharmony_ci		} else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) {
838c2ecf20Sopenharmony_ci			printf(_("System does not support Intel's performance"
848c2ecf20Sopenharmony_ci				 " bias setting\n"));
858c2ecf20Sopenharmony_ci			params.perf_bias = 0;
868c2ecf20Sopenharmony_ci		}
878c2ecf20Sopenharmony_ci	}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	/* loop over CPUs */
908c2ecf20Sopenharmony_ci	for (cpu = bitmask_first(cpus_chosen);
918c2ecf20Sopenharmony_ci	     cpu <= bitmask_last(cpus_chosen); cpu++) {
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci		if (!bitmask_isbitset(cpus_chosen, cpu))
948c2ecf20Sopenharmony_ci			continue;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci		printf(_("analyzing CPU %d:\n"), cpu);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		if (sysfs_is_cpu_online(cpu) != 1){
998c2ecf20Sopenharmony_ci			printf(_(" *is offline\n"));
1008c2ecf20Sopenharmony_ci			continue;
1018c2ecf20Sopenharmony_ci		}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci		if (params.perf_bias) {
1048c2ecf20Sopenharmony_ci			ret = msr_intel_get_perf_bias(cpu);
1058c2ecf20Sopenharmony_ci			if (ret < 0) {
1068c2ecf20Sopenharmony_ci				fprintf(stderr,
1078c2ecf20Sopenharmony_ci			_("Could not read perf-bias value[%d]\n"), ret);
1088c2ecf20Sopenharmony_ci				exit(EXIT_FAILURE);
1098c2ecf20Sopenharmony_ci			} else
1108c2ecf20Sopenharmony_ci				printf(_("perf-bias: %d\n"), ret);
1118c2ecf20Sopenharmony_ci		}
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci	return 0;
1148c2ecf20Sopenharmony_ci}
115