Skip to content

Commit 997074d

Browse files
committed
tools/power/x86/intel-speed-select: Use cgroup v2 isolation
On supported systems, it is possiible to isolate CPUs instead of CPU online/offline. This is optional and can be specified using -g option when running as daemon or in combination with -o option for SST-PP level change. CPU isolation doesn't isolate IRQs. So IRQs needs to be moved away from isoolated CPUs. This can be done via IRQ sysfs or irqbalance daemon. The IRQ balance daemon is also capable to parse thermal HFI messages to move IRQs away from CPUS, which are supposed be isolated. But this requires version released after July 2022. Signed-off-by: Srinivas Pandruvada <[email protected]>
1 parent 57797f1 commit 997074d

File tree

3 files changed

+173
-2
lines changed

3 files changed

+173
-2
lines changed

tools/power/x86/intel-speed-select/isst-config.c

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ static int cmd_help;
4444
static int force_online_offline;
4545
static int auto_mode;
4646
static int fact_enable_fail;
47+
static int cgroupv2;
4748

4849
/* clos related */
4950
static int current_clos = -1;
@@ -834,7 +835,137 @@ int find_phy_core_num(int logical_cpu)
834835
return -EINVAL;
835836
}
836837

838+
int use_cgroupv2(void)
839+
{
840+
return cgroupv2;
841+
}
842+
843+
int enable_cpuset_controller(void)
844+
{
845+
int fd, ret;
846+
847+
fd = open("/sys/fs/cgroup/cgroup.subtree_control", O_RDWR, 0);
848+
if (fd < 0) {
849+
debug_printf("Can't activate cpuset controller\n");
850+
debug_printf("Either you are not root user or CGroup v2 is not supported\n");
851+
return fd;
852+
}
853+
854+
ret = write(fd, " +cpuset", strlen(" +cpuset"));
855+
close(fd);
856+
857+
if (ret == -1) {
858+
debug_printf("Can't activate cpuset controller: Write failed\n");
859+
return ret;
860+
}
861+
862+
return 0;
863+
}
864+
865+
int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level)
866+
{
867+
int i, first, curr_index, index, ret, fd;
868+
static char str[512], dir_name[64];
869+
static char cpuset_cpus[128];
870+
int str_len = sizeof(str);
871+
DIR *dir;
872+
873+
snprintf(dir_name, sizeof(dir_name), "/sys/fs/cgroup/%d-%d-%d", id->pkg, id->die, id->punit);
874+
dir = opendir(dir_name);
875+
if (!dir) {
876+
ret = mkdir(dir_name, 0744);
877+
if (ret) {
878+
debug_printf("Can't create dir:%s errno:%d\n", dir_name, errno);
879+
return ret;
880+
}
881+
}
882+
closedir(dir);
883+
884+
if (!level) {
885+
sprintf(cpuset_cpus, "%s/cpuset.cpus.partition", dir_name);
886+
887+
fd = open(cpuset_cpus, O_RDWR, 0);
888+
if (fd < 0) {
889+
return fd;
890+
}
891+
892+
ret = write(fd, "member", strlen("member"));
893+
if (ret == -1) {
894+
printf("Can't update to member\n");
895+
return ret;
896+
}
897+
898+
return 0;
899+
}
900+
901+
if (!CPU_COUNT_S(mask_size, cpu_mask)) {
902+
return -1;
903+
}
837904

905+
curr_index = 0;
906+
first = 1;
907+
str[0] = '\0';
908+
for (i = 0; i < get_topo_max_cpus(); ++i) {
909+
if (!is_cpu_in_power_domain(i, id))
910+
continue;
911+
912+
if (CPU_ISSET_S(i, mask_size, cpu_mask))
913+
continue;
914+
915+
if (!first) {
916+
index = snprintf(&str[curr_index],
917+
str_len - curr_index, ",");
918+
curr_index += index;
919+
if (curr_index >= str_len)
920+
break;
921+
}
922+
index = snprintf(&str[curr_index], str_len - curr_index, "%d",
923+
i);
924+
curr_index += index;
925+
if (curr_index >= str_len)
926+
break;
927+
first = 0;
928+
}
929+
930+
debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str);
931+
932+
snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name);
933+
934+
fd = open(cpuset_cpus, O_RDWR, 0);
935+
if (fd < 0) {
936+
return fd;
937+
}
938+
939+
ret = write(fd, str, strlen(str));
940+
close(fd);
941+
942+
if (ret == -1) {
943+
debug_printf("Can't activate cpuset controller: Write failed\n");
944+
return ret;
945+
}
946+
947+
snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus.partition", dir_name);
948+
949+
fd = open(cpuset_cpus, O_RDWR, 0);
950+
if (fd < 0) {
951+
return fd;
952+
}
953+
954+
ret = write(fd, "isolated", strlen("isolated"));
955+
if (ret == -1) {
956+
debug_printf("Can't update to isolated\n");
957+
ret = write(fd, "root", strlen("root"));
958+
if (ret == -1)
959+
debug_printf("Can't update to root\n");
960+
}
961+
962+
close(fd);
963+
964+
if (ret < 0)
965+
return ret;
966+
967+
return 0;
968+
}
838969

839970
static int isst_fill_platform_info(void)
840971
{
@@ -1273,6 +1404,23 @@ static void set_tdp_level_for_cpu(struct isst_id *id, void *arg1, void *arg2, vo
12731404
isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
12741405
goto free_mask;
12751406
}
1407+
1408+
if (use_cgroupv2()) {
1409+
int ret;
1410+
1411+
fprintf(stderr, "Using cgroup v2 in lieu of online/offline\n");
1412+
ret = enable_cpuset_controller();
1413+
if (ret)
1414+
goto use_offline;
1415+
1416+
ret = isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, tdp_level);
1417+
if (ret)
1418+
goto use_offline;
1419+
1420+
goto free_mask;
1421+
}
1422+
1423+
use_offline:
12761424
if (ctdp_level.cpu_count) {
12771425
int i, max_cpus = get_topo_max_cpus();
12781426
for (i = 0; i < max_cpus; ++i) {
@@ -2787,6 +2935,7 @@ static void usage(void)
27872935
printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n");
27882936
printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
27892937
printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
2938+
printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n");
27902939
printf("\nResult format\n");
27912940
printf("\tResult display uses a common format for each command:\n");
27922941
printf("\tResults are formatted in text/JSON with\n");
@@ -2839,6 +2988,7 @@ static void cmdline(int argc, char **argv)
28392988
{ "oob", no_argument, 0, 'b' },
28402989
{ "no-daemon", no_argument, 0, 'n' },
28412990
{ "poll-interval", required_argument, 0, 'w' },
2991+
{ "cgroupv2", required_argument, 0, 'g' },
28422992
{ 0, 0, 0, 0 }
28432993
};
28442994

@@ -2869,7 +3019,7 @@ static void cmdline(int argc, char **argv)
28693019
goto out;
28703020

28713021
progname = argv[0];
2872-
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:n", long_options,
3022+
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ng", long_options,
28733023
&option_index)) != -1) {
28743024
switch (opt) {
28753025
case 'a':
@@ -2928,6 +3078,9 @@ static void cmdline(int argc, char **argv)
29283078
}
29293079
poll_interval = ret;
29303080
break;
3081+
case 'g':
3082+
cgroupv2 = 1;
3083+
break;
29313084
default:
29323085
usage();
29333086
}

tools/power/x86/intel-speed-select/isst-daemon.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ void process_level_change(struct isst_id *id)
8383
return;
8484
}
8585

86+
if (use_cgroupv2()) {
87+
int ret;
88+
89+
ret = enable_cpuset_controller();
90+
if (ret)
91+
goto use_offline;
92+
93+
isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, pkg_dev.current_level);
94+
95+
goto free_mask;
96+
}
97+
98+
use_offline:
8699
if (ctdp_level.cpu_count) {
87100
int i, max_cpus = get_topo_max_cpus();
88101
for (i = 0; i < max_cpus; ++i) {
@@ -97,7 +110,7 @@ void process_level_change(struct isst_id *id)
97110
}
98111
}
99112
}
100-
113+
free_mask:
101114
free_cpu_set(ctdp_level.core_cpumask);
102115
}
103116

tools/power/x86/intel-speed-select/isst.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,4 +315,9 @@ extern void hfi_exit(void);
315315
extern struct isst_platform_ops *mbox_get_platform_ops(void);
316316
extern struct isst_platform_ops *tpmi_get_platform_ops(void);
317317

318+
/* Cgroup related interface */
319+
extern int enable_cpuset_controller(void);
320+
extern int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level);
321+
extern int use_cgroupv2(void);
322+
318323
#endif

0 commit comments

Comments
 (0)