Skip to content

Commit

Permalink
tools/power/x86/intel-speed-select: Use cgroup v2 isolation
Browse files Browse the repository at this point in the history
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 <srinivas.pandruvada@linux.intel.com>
  • Loading branch information
Srinivas Pandruvada committed Mar 22, 2023
1 parent 57797f1 commit 997074d
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 2 deletions.
155 changes: 154 additions & 1 deletion tools/power/x86/intel-speed-select/isst-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ static int cmd_help;
static int force_online_offline;
static int auto_mode;
static int fact_enable_fail;
static int cgroupv2;

/* clos related */
static int current_clos = -1;
Expand Down Expand Up @@ -834,7 +835,137 @@ int find_phy_core_num(int logical_cpu)
return -EINVAL;
}

int use_cgroupv2(void)
{
return cgroupv2;
}

int enable_cpuset_controller(void)
{
int fd, ret;

fd = open("/sys/fs/cgroup/cgroup.subtree_control", O_RDWR, 0);
if (fd < 0) {
debug_printf("Can't activate cpuset controller\n");
debug_printf("Either you are not root user or CGroup v2 is not supported\n");
return fd;
}

ret = write(fd, " +cpuset", strlen(" +cpuset"));
close(fd);

if (ret == -1) {
debug_printf("Can't activate cpuset controller: Write failed\n");
return ret;
}

return 0;
}

int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level)
{
int i, first, curr_index, index, ret, fd;
static char str[512], dir_name[64];
static char cpuset_cpus[128];
int str_len = sizeof(str);
DIR *dir;

snprintf(dir_name, sizeof(dir_name), "/sys/fs/cgroup/%d-%d-%d", id->pkg, id->die, id->punit);
dir = opendir(dir_name);
if (!dir) {
ret = mkdir(dir_name, 0744);
if (ret) {
debug_printf("Can't create dir:%s errno:%d\n", dir_name, errno);
return ret;
}
}
closedir(dir);

if (!level) {
sprintf(cpuset_cpus, "%s/cpuset.cpus.partition", dir_name);

fd = open(cpuset_cpus, O_RDWR, 0);
if (fd < 0) {
return fd;
}

ret = write(fd, "member", strlen("member"));
if (ret == -1) {
printf("Can't update to member\n");
return ret;
}

return 0;
}

if (!CPU_COUNT_S(mask_size, cpu_mask)) {
return -1;
}

curr_index = 0;
first = 1;
str[0] = '\0';
for (i = 0; i < get_topo_max_cpus(); ++i) {
if (!is_cpu_in_power_domain(i, id))
continue;

if (CPU_ISSET_S(i, mask_size, cpu_mask))
continue;

if (!first) {
index = snprintf(&str[curr_index],
str_len - curr_index, ",");
curr_index += index;
if (curr_index >= str_len)
break;
}
index = snprintf(&str[curr_index], str_len - curr_index, "%d",
i);
curr_index += index;
if (curr_index >= str_len)
break;
first = 0;
}

debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str);

snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name);

fd = open(cpuset_cpus, O_RDWR, 0);
if (fd < 0) {
return fd;
}

ret = write(fd, str, strlen(str));
close(fd);

if (ret == -1) {
debug_printf("Can't activate cpuset controller: Write failed\n");
return ret;
}

snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus.partition", dir_name);

fd = open(cpuset_cpus, O_RDWR, 0);
if (fd < 0) {
return fd;
}

ret = write(fd, "isolated", strlen("isolated"));
if (ret == -1) {
debug_printf("Can't update to isolated\n");
ret = write(fd, "root", strlen("root"));
if (ret == -1)
debug_printf("Can't update to root\n");
}

close(fd);

if (ret < 0)
return ret;

return 0;
}

static int isst_fill_platform_info(void)
{
Expand Down Expand Up @@ -1273,6 +1404,23 @@ static void set_tdp_level_for_cpu(struct isst_id *id, void *arg1, void *arg2, vo
isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
goto free_mask;
}

if (use_cgroupv2()) {
int ret;

fprintf(stderr, "Using cgroup v2 in lieu of online/offline\n");
ret = enable_cpuset_controller();
if (ret)
goto use_offline;

ret = isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, tdp_level);
if (ret)
goto use_offline;

goto free_mask;
}

use_offline:
if (ctdp_level.cpu_count) {
int i, max_cpus = get_topo_max_cpus();
for (i = 0; i < max_cpus; ++i) {
Expand Down Expand Up @@ -2787,6 +2935,7 @@ static void usage(void)
printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n");
printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n");
printf("\nResult format\n");
printf("\tResult display uses a common format for each command:\n");
printf("\tResults are formatted in text/JSON with\n");
Expand Down Expand Up @@ -2839,6 +2988,7 @@ static void cmdline(int argc, char **argv)
{ "oob", no_argument, 0, 'b' },
{ "no-daemon", no_argument, 0, 'n' },
{ "poll-interval", required_argument, 0, 'w' },
{ "cgroupv2", required_argument, 0, 'g' },
{ 0, 0, 0, 0 }
};

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

progname = argv[0];
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:n", long_options,
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ng", long_options,
&option_index)) != -1) {
switch (opt) {
case 'a':
Expand Down Expand Up @@ -2928,6 +3078,9 @@ static void cmdline(int argc, char **argv)
}
poll_interval = ret;
break;
case 'g':
cgroupv2 = 1;
break;
default:
usage();
}
Expand Down
15 changes: 14 additions & 1 deletion tools/power/x86/intel-speed-select/isst-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ void process_level_change(struct isst_id *id)
return;
}

if (use_cgroupv2()) {
int ret;

ret = enable_cpuset_controller();
if (ret)
goto use_offline;

isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, pkg_dev.current_level);

goto free_mask;
}

use_offline:
if (ctdp_level.cpu_count) {
int i, max_cpus = get_topo_max_cpus();
for (i = 0; i < max_cpus; ++i) {
Expand All @@ -97,7 +110,7 @@ void process_level_change(struct isst_id *id)
}
}
}

free_mask:
free_cpu_set(ctdp_level.core_cpumask);
}

Expand Down
5 changes: 5 additions & 0 deletions tools/power/x86/intel-speed-select/isst.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,9 @@ extern void hfi_exit(void);
extern struct isst_platform_ops *mbox_get_platform_ops(void);
extern struct isst_platform_ops *tpmi_get_platform_ops(void);

/* Cgroup related interface */
extern int enable_cpuset_controller(void);
extern int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level);
extern int use_cgroupv2(void);

#endif

0 comments on commit 997074d

Please sign in to comment.