Skip to content

Commit 54b295f

Browse files
committed
The latest kernels allow for users to get/set the DSCR value on a per process.
This allows for more refined DSCR setting in applications. This is implemented by using the ptrace peekuser capabilites in the kernel and simply doing a ptrace attach and peek from the ppc64_cpu command. Note: this does not actually stop the process we are attaching to while under ptrace control. The patch does a little more than just adding this functionality since the --dscr commad now takes an optional -p <pid> option. This required an updated to the command parsing code to allow this. Signed-off-by: Nathan Fontenot <[email protected]>
1 parent 90029c9 commit 54b295f

File tree

1 file changed

+123
-49
lines changed

1 file changed

+123
-49
lines changed

src/ppc64_cpu.c

Lines changed: 123 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <assert.h>
2121
#include <pthread.h>
2222
#include <sys/ioctl.h>
23+
#include <sys/ptrace.h>
24+
#include <sys/wait.h>
2325
#ifdef HAVE_LINUX_PERF_EVENT_H
2426
#include <linux/perf_event.h>
2527
#endif
@@ -483,15 +485,61 @@ int do_smt(char *state)
483485
return rc;
484486
}
485487

486-
int do_dscr(char *state)
488+
#define PTRACE_DSCR 44
489+
490+
int do_dscr_pid(int dscr_state, pid_t pid)
491+
{
492+
int rc;
493+
494+
rc = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
495+
if (rc) {
496+
fprintf(stderr, "Could not attach to process %d to %s the "
497+
"DSCR value\n%s\n", pid, (dscr_state ? "set" : "get"),
498+
strerror(errno));
499+
return rc;
500+
}
501+
502+
wait(NULL);
503+
504+
if (dscr_state) {
505+
rc = ptrace(PTRACE_POKEUSER, pid, PTRACE_DSCR << 3, dscr_state);
506+
if (rc) {
507+
fprintf(stderr, "Could not set the DSCR value for pid "
508+
"%d\n%s\n", pid, strerror(errno));
509+
ptrace(PTRACE_DETACH, pid, NULL, NULL);
510+
return rc;
511+
}
512+
}
513+
514+
rc = ptrace(PTRACE_PEEKUSER, pid, PTRACE_DSCR << 3, NULL);
515+
if (errno) {
516+
fprintf(stderr, "Could not get the DSCR value for pid "
517+
"%d\n%s\n", pid, strerror(errno));
518+
rc = -1;
519+
} else {
520+
printf("DSCR for pid %d is %d\n", pid, rc);
521+
}
522+
523+
ptrace(PTRACE_DETACH, pid, NULL, NULL);
524+
return rc;
525+
}
526+
527+
int do_dscr(char *state, pid_t pid)
487528
{
488529
int rc = 0;
530+
int dscr_state = 0;
489531

490532
if (!is_dscr_capable()) {
491533
fprintf(stderr, "Machine is not DSCR capable\n");
492534
return -1;
493535
}
494536

537+
if (state)
538+
dscr_state = strtol(state, NULL, 0);
539+
540+
if (pid != -1)
541+
return do_dscr_pid(dscr_state, pid);
542+
495543
if (!state) {
496544
int dscr;
497545

@@ -504,11 +552,11 @@ int do_dscr(char *state)
504552
if (dscr == -1)
505553
printf("Inconsistent DSCR\n");
506554
else
507-
printf("dscr is %d\n", dscr);
555+
printf("DSCR is %d\n", dscr);
508556
break;
509557
}
510558
} else
511-
rc = set_dscr(strtol(state, NULL, 0));
559+
rc = set_dscr(dscr_state);
512560

513561
return rc;
514562
}
@@ -908,20 +956,23 @@ int do_cores_online(char *state)
908956

909957
void usage(void)
910958
{
911-
printf("\tppc64_cpu --smt # Get current SMT state\n"
912-
"\tppc64_cpu --smt={on|off} # Turn SMT on/off\n"
913-
"\tppc64_cpu --smt=X # Set SMT state to X\n\n"
914-
"\tppc64_cpu --cores-present # Get the number of cores installed\n"
915-
"\tppc64_cpu --cores-on # Get the number of cores currently online\n"
916-
"\tppc64_cpu --cores-on=X # Put exactly X cores online\n\n"
917-
918-
"\tppc64_cpu --dscr # Get current DSCR setting\n"
919-
"\tppc64_cpu --dscr=<val> # Change DSCR setting\n\n"
920-
"\tppc64_cpu --smt-snooze-delay # Get current smt-snooze-delay setting\n"
921-
"\tppc64_cpu --smt-snooze-delay=<val> # Change smt-snooze-delay setting\n\n"
922-
"\tppc64_cpu --run-mode # Get current diagnostics run mode\n"
923-
"\tppc64_cpu --run-mode=<val> # Set current diagnostics run mode\n\n"
924-
"\tppc64_cpu --frequency # Determine cpu frequency.\n\n");
959+
printf(
960+
"Usage: ppc64_cpu [command] [options]\n"
961+
"ppc64_cpu --smt # Get current SMT state\n"
962+
"ppc64_cpu --smt={on|off} # Turn SMT on/off\n"
963+
"ppc64_cpu --smt=X # Set SMT state to X\n\n"
964+
"ppc64_cpu --cores-present # Get the number of cores present\n"
965+
"ppc64_cpu --cores-on # Get the number of cores currently online\n"
966+
"ppc64_cpu --cores-on=X # Put exactly X cores online\n\n"
967+
"ppc64_cpu --dscr # Get current DSCR system setting\n"
968+
"ppc64_cpu --dscr=<val> # Change DSCR system setting\n"
969+
"ppc64_cpu --dscr [-p <pid>] # Get DSCR setting for process <pid>\n"
970+
"ppc64_cpu --dscr=<val> [-p <pid>] # Change DSCR setting for process <pid>\n\n"
971+
"ppc64_cpu --smt-snooze-delay # Get current smt-snooze-delay setting\n"
972+
"ppc64_cpu --smt-snooze-delay=<val> # Change smt-snooze-delay setting\n\n"
973+
"ppc64_cpu --run-mode # Get current diagnostics run mode\n"
974+
"ppc64_cpu --run-mode=<val> # Set current diagnostics run mode\n\n"
975+
"ppc64_cpu --frequency # Determine cpu frequency.\n\n");
925976
}
926977

927978
struct option longopts[] = {
@@ -939,8 +990,11 @@ struct option longopts[] = {
939990
int main(int argc, char *argv[])
940991
{
941992
int rc = 0;
993+
char *action;
994+
char *action_arg = NULL;
995+
char *equal_char;
942996
int opt;
943-
int option_index;
997+
pid_t pid = -1;
944998

945999
if (argc == 1) {
9461000
usage();
@@ -953,47 +1007,67 @@ int main(int argc, char *argv[])
9531007
return rc;
9541008
}
9551009

956-
while (1) {
957-
opt = getopt_long(argc, argv, "s::d::S::r::fCVc::", longopts,
958-
&option_index);
959-
if (opt == -1)
960-
break;
1010+
/* The first arg is the action to be taken with an optional action
1011+
* arg in the form --action=XXX. Parse this out so we can call the
1012+
* appropriate action.
1013+
*/
1014+
action = argv[1];
9611015

962-
switch (opt) {
963-
case 's':
964-
rc = do_smt(optarg);
965-
break;
966-
967-
case 'd':
968-
rc = do_dscr(optarg);
969-
break;
1016+
/* skipp past the '--' */
1017+
action += 2;
9701018

971-
case 'S':
972-
rc = do_smt_snooze_delay(optarg);
973-
break;
1019+
equal_char = strchr(action, '=');
1020+
if (equal_char) {
1021+
*equal_char = '\0';
1022+
action_arg = equal_char + 1;
1023+
}
9741024

975-
case 'r':
976-
rc = do_run_mode(optarg);
1025+
/* Now parse out any additional options. Currently there is only
1026+
* the -p <pid> option for the --dscr action.
1027+
*/
1028+
optind = 2;
1029+
while (1) {
1030+
opt = getopt(argc, argv, "p:");
1031+
if (opt == -1)
9771032
break;
9781033

979-
case 'f':
980-
rc = do_cpu_frequency();
981-
break;
1034+
switch (opt) {
1035+
case 'p':
1036+
/* only valid for do_dscr option */
1037+
if (strcmp(action, "dscr")) {
1038+
fprintf(stderr, "The p option is only valid "
1039+
"with the --dscr option\n");
1040+
usage();
1041+
exit(-1);
1042+
}
9821043

983-
case 'C':
984-
rc = do_cores_present(optarg);
1044+
pid = atoi(optarg);
9851045
break;
986-
case 'c':
987-
rc = do_cores_online(optarg);
988-
break;
989-
case 'V':
990-
printf("ppc64_cpu: version %s\n", PPC64_CPU_VERSION);
991-
break;
992-
default:
1046+
default:
1047+
fprintf(stderr, "%c is not a valid option\n", opt);
9931048
usage();
994-
break;
1049+
exit(-1);
9951050
}
9961051
}
9971052

1053+
if (!strcmp(action, "smt"))
1054+
rc = do_smt(action_arg);
1055+
else if (!strcmp(action, "dscr"))
1056+
rc = do_dscr(action_arg, pid);
1057+
else if (!strcmp(action, "smt-snooze-delay"))
1058+
rc = do_smt_snooze_delay(action_arg);
1059+
else if (!strcmp(action, "run-mode"))
1060+
rc = do_run_mode(action_arg);
1061+
else if (!strcmp(action, "frequency"))
1062+
rc = do_cpu_frequency();
1063+
else if (!strcmp(action, "cores-present"))
1064+
rc = do_cores_present(action_arg);
1065+
else if (!strcmp(action, "cores-on"))
1066+
rc = do_cores_online(action_arg);
1067+
else if (!strcmp(action, "version"))
1068+
printf("ppc64_cpu: version %s\n", PPC64_CPU_VERSION);
1069+
else
1070+
usage();
1071+
9981072
return rc;
9991073
}

0 commit comments

Comments
 (0)