Beispiel #1
0
 static std::string error_message(int err)
 {
     char tmp_msg[NAME_MAX];
     err = err ? err : GEOPM_ERROR_RUNTIME;
     geopm_error_message(err, tmp_msg, sizeof(tmp_msg));
     return tmp_msg;
 }
int main(int argc, char **argv)
{
    int err = 0;
    char error_msg[512];

    if (argc == 2 &&
        strncmp(argv[1], "crc32", strlen("crc32") + 1) == 0) {
        uint64_t result = geopm_crc32_u64(0xDEADBEEF, 0xBADFEE);
        if (result == 0xA347ADE3 ) {
            std::cout << "Platform supports crc32 intrinsic." << std::endl;
        }
        else {
            err = GEOPM_ERROR_PLATFORM_UNSUPPORTED;
            std::cerr << "Warning: <geopm_platform_supported>: Platform does not support crc32 intrinsic." << std::endl;
        }
    }
    else {
        int cpu_id = geopm_read_cpuid();
        if (cpu_id != 0x63F &&
            cpu_id != 0x63F &&
            cpu_id != 0x63E &&
            cpu_id != 0x62D &&
            cpu_id != 0x64F &&
            cpu_id != 0x657) {
            err = GEOPM_ERROR_PLATFORM_UNSUPPORTED;
            geopm_error_message(err, error_msg, 512);
            std::cerr << "Warning: <geopm_platform_supported>: Platform 0x" << std::hex << cpu_id << " is not a supported CPU" << " " << error_msg << "." << std::endl;
        }
        if (!err) {
            int fd = open("/dev/cpu/0/msr_safe", O_RDONLY);
            if (fd == -1) {
                err = GEOPM_ERROR_MSR_OPEN;
                geopm_error_message(err, error_msg, 512);
                std::cerr << "Warning: <geopm_platform_supported>: Not able to open msr_safe device. " << error_msg << "." << std::endl;

            }
            else {
                close(fd);
            }
        }
        if (!err) {
           std::cout << "Platform 0x" << std::hex << cpu_id << " is supported by geopm and msr_safe is available." << std::endl;
        }
    }
    return err;
}
Beispiel #3
0
int main(int argc, char **argv)
{
    int err = 0;
    int rank;
    int verbosity = 0;
    uint64_t init_rid;
    char *config_path = NULL;
    const char *usage = "\n"
"%s -h | --help\n"
"    Print this help message.\n"
"\n"
"%s [--verbose] [config_file]\n"
"\n"
"    --verbose: Print output from rank zero as every region executes.\n"
"\n"
"    config_file: Path to json file containing loop count and sequence\n"
"                 of regions in each loop.\n"
"\n"
"                 Example configuration json string:\n"
"\n"
"                 {\"loop-count\": 10,\n"
"                  \"region\": [\"sleep\", \"stream\", \"dgemm\", \"stream\", \"all2all\"],\n"
"                  \"big-o\": [1.0, 1.0, 1.0, 1.0, 1.0]}\n"
"\n"
"                 The \"loop-count\" value is an integer that sets the\n"
"                 number of loops executed.  Each time through the loop\n"
"                 the regions listed in the \"region\" array are\n"
"                 executed.  The \"big-o\" array gives double precision\n"
"                 values for each region.  Region names can be one of\n"
"                 the following options:\n"
"\n"
"                 sleep: Executes clock_nanosleep() for big-o seconds.\n"
"\n"
"                 spin: Executes a spin loop for big-o seconds.\n"
"\n"
"                 stream: Executes stream \"triadd\" on a vector with\n"
"                 length proportional to big-o.\n"
"\n"
"                 dgemm: Dense matrix-matrix multiply with floating\n"
"                 point operations proportional to big-o.\n"
"\n"
"                 all2all: All processes send buffers to all other\n"
"                 processes.  The time of this operation is\n"
"                 proportional to big-o.\n"
"\n"
"                 Example configuration json string with imbalance and\n"
"                 progress:\n"
"\n"
"                 {\"loop-count\": 10,\n"
"                  \"region\": [\"sleep\", \"stream-progress\", \"dgemm-imbalance\", \"stream\", \"all2all\"],\n"
"                  \"big-o\": [1.0, 1.0, 1.0, 1.0, 1.0],\n"
"                  \"hostname\": [\"compute-node-3\", \"compute-node-15\"],\n"
"                  \"imbalance\": [0.05, 0.15]}\n"
"\n"
"                 If \"-imbalance\" is appended to any region name in\n"
"                 the configuration file and the \"hostname\" and\n"
"                 \"imbalance\" fields are provided then those\n"
"                 regions will have an injected delay on the hosts\n"
"                 listed.  In the above example a 5%% delay on\n"
"                 \"my-compute-node-3\" and a 15%% delay on\n"
"                 \"my-compute-node-15\" are injected when executing\n"
"                 the dgemm region.\n"
"\n"
"                 If \"-progress\" is appended to any region name in the\n"
"                 configuration, then progress for the region will be\n"
"                 reported through the geopm_prof_progress API.\n"
"\n"
"\n";

    err = MPI_Init(&argc, &argv);
    if (!err) {
        err = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    }

    if (!err && argc > 1) {
        if (strncmp(argv[1], "--help", strlen("--help")) == 0 ||
            strncmp(argv[1], "-h", strlen("-h")) == 0) {
            if (!rank) {
                printf(usage, argv[0], argv[0]);
            }
            return 0;
        }
        int offset = 1;
        if (strncmp(argv[1], "--verbose", strlen("--verbose")) == 0) {
            if (!rank) {
                verbosity = 1;
            }
            ++offset;
        }
        if (argc > offset) {
            config_path = argv[offset];
        }
    }

    if (!err) {
        err = geopm_prof_region("model-init", GEOPM_POLICY_HINT_UNKNOWN, &init_rid);
    }
    if (!err) {
        err = geopm_prof_enter(init_rid);
    }
    if (!err) {
        // Do application initialization
        uint64_t loop_count = 0;
        std::vector<std::string> region_sequence;
        std::vector<double> big_o_sequence;
        if (config_path) {
            geopm::model_parse_config(config_path, loop_count, region_sequence, big_o_sequence);
        }
        else {
            // Default values if no configuration is specified
            loop_count = 10;
            region_sequence = {"sleep", "stream", "dgemm", "stream", "all2all"};
            big_o_sequence = {1.0, 1.0, 1.0, 1.0, 1.0};
        }
        geopm::ModelApplication app(loop_count, region_sequence, big_o_sequence, verbosity, rank);
        err = geopm_prof_exit(init_rid);
        if (!err) {
            // Run application
            app.run();
        }
    }
    if (!err) {
        err = MPI_Finalize();
    }
    if (err) {
        char err_msg[NAME_MAX];
        geopm_error_message(err, err_msg, NAME_MAX);
        std::cerr << "ERROR: " << argv[0] << ": " << err_msg << std::endl;
    }
    return err;
}
Beispiel #4
0
int main(int argc, char **argv)
{
    int opt;
    int err = 0;
    int output_num;
    double policy_vals[GEOPMAGENT_DOUBLE_LENGTH] = {0};
    char error_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char agent_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char policy_vals_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char output_str[NAME_MAX * GEOPMAGENT_DOUBLE_LENGTH];
    char *agent_ptr = NULL;
    char *policy_vals_ptr = NULL;
    char *arg_ptr = NULL;
    const char *usage = "\nUsage: geopmagent\n"
                        "       geopmagent [-a AGENT] [-p POLICY0,POLICY1,...]\n"
                        "       geopmagent [--help] [--version]\n"
                        "\n"
                        "Mandatory arguments to long options are mandatory for short options too.\n"
                        "\n"
                        "  -a, --agent=AGENT         specify the name of the agent\n"
                        "  -p, --policy=POLICY0,...  values to be set for each policy in a\n"
                        "                            comma-seperated list\n"
                        "  -h, --help                print  brief summary of the command line\n"
                        "                            usage information, then exit\n"
                        "  -v, --version             print version of GEOPM to standard output,\n"
                        "                            then exit\n"
                        "\n"
                        "Copyright (c) 2015, 2016, 2017, 2018, Intel Corporation. All rights reserved.\n"
                        "\n";

    static struct option long_options[] = {
        {"agent", required_argument, NULL, 'a'},
        {"policy", required_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {"version", no_argument, NULL, 'v'},
        {NULL, 0, NULL, 0}
    };

    while (!err && (opt = getopt_long(argc, argv, "a:p:hv", long_options, NULL)) != -1) {
        arg_ptr = NULL;
        switch (opt) {
            case 'a':
                arg_ptr = agent_str;
                break;
            case 'p':
                arg_ptr = policy_vals_str;
                break;
            case 'h':
                printf("%s", usage);
                return 0;
            case 'v':
                printf("%s\n", geopm_version());
                printf("\n\nCopyright (c) 2015, 2016, 2017, 2018, Intel Corporation. All rights reserved.\n\n");
                return 0;
            case '?': // opt is ? when an option required an arg but it was missing
                fprintf(stderr, usage, argv[0]);
                err = EINVAL;
                break;
            default:
                fprintf(stderr, "Error: getopt returned character code \"0%o\"\n", opt);
                err = EINVAL;
                break;
        }

        if (!err) {
            strncpy(arg_ptr, optarg, GEOPMAGENT_STRING_LENGTH);
            if (arg_ptr[GEOPMAGENT_STRING_LENGTH - 1] != '\0') {
                fprintf(stderr, "Error: config_file name too long\n");
                err = EINVAL;
            }
        }
    }

    if (!err && optind != argc) {
        fprintf(stderr, "Error: The following positional argument(s) are in error:\n");
        while (optind < argc) {
            fprintf(stderr, "%s\n", argv[optind++]);
        }
        err = EINVAL;
    }

    if (!err) {
        if (strnlen(agent_str, GEOPMAGENT_STRING_LENGTH)) {
            agent_ptr = agent_str;
        }
        if (strnlen(policy_vals_str, GEOPMAGENT_STRING_LENGTH)) {
            policy_vals_ptr = policy_vals_str;
        }
    }

    if (!err && argc == 1) {
        err = geopm_agent_num_avail(&output_num);
        if (!err) {
            for(int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_name(i, sizeof(output_str), output_str);
                if (!err) {
                    printf("%s\n", output_str);
                }
            }
        }
    }
    else if (!err && agent_ptr != NULL && policy_vals_ptr == NULL) {
        err = geopm_agent_supported(agent_ptr);

        // Policies
        if (!err) {
            err = geopm_agent_num_policy(agent_ptr, &output_num);
        }

        if (!err) {
            printf("Policy: ");
            for (int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_policy_name(agent_ptr, i, sizeof(output_str), output_str);
                if (!err) {
                    if (i > 0) {
                        printf(",");
                    }
                    printf("%s", output_str);
                }
            }
            if (!err && output_num == 0) {
                printf("(none)\n");
            }
            else {
                printf("\n");
            }
        }

        // Samples
        if (!err) {
            err = geopm_agent_num_sample(agent_ptr, &output_num);
        }

        if (!err) {
            printf("Sample: ");
            for (int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_sample_name(agent_ptr, i, sizeof(output_str), output_str);
                if (!err) {
                    if (i > 0) {
                        printf(",");
                    }
                    printf("%s", output_str);
                }
            }
            if (!err && output_num == 0) {
                printf("(none)\n");
            }
            else {
                printf("\n");
            }
        }
    }
    else if (!err) {

        if (agent_ptr == NULL) {
            fprintf(stderr, "Error: Agent (-a) must be specified to create a policy.\n");
            err = EINVAL;
        }

        int num_policy = 0;
        if (!err) {
            err = geopm_agent_num_policy(agent_ptr, &num_policy);
        }

        if (!err) {
            if (num_policy) {
                int policy_count = 0;
                char *tok = strtok(policy_vals_ptr, ",");
                while (!err && tok != NULL) {
                    policy_vals[policy_count++] = atof(tok);
                    if (policy_count > GEOPMAGENT_DOUBLE_LENGTH) {
                        err = E2BIG;
                    }
                    tok = strtok(NULL, ",");
                }
                if (!err && num_policy != policy_count) {
                    fprintf(stderr, "Error: Number of policies read from command line does not match agent.\n");
                    err = EINVAL;
                }
            }
            else if (strncmp(policy_vals_ptr, "none", 4) != 0 &&
                     strncmp(policy_vals_ptr, "None", 4) != 0) {
                fprintf(stderr, "Error: Must specify \"None\" for the parameter option if agent takes no parameters.\n");
                err = EINVAL;
            }
        }
        if(!err) {
            err = geopm_agent_policy_json(agent_ptr, policy_vals, sizeof(output_str), output_str);
            printf("%s\n", output_str);
        }
    }

    if (err) {
        geopm_error_message(err, error_str, GEOPMAGENT_STRING_LENGTH);
        fprintf(stderr, "Error: %s\n", error_str);
    }

    return err;
}
Beispiel #5
0
int main(int argc, char** argv)
{
    int opt;
    int err = 0;
    int exec_mode = 0;
    char file[GEOPMPOLICY_STRING_LENGTH] = {0};
    char mode_string[GEOPMPOLICY_STRING_LENGTH] = {0};
    char option_string[GEOPMPOLICY_STRING_LENGTH] = {0};
    char copy_string[GEOPMPOLICY_STRING_LENGTH] = {0};
    char error_string[GEOPMPOLICY_STRING_LENGTH] = {0};
    FILE *infile;
    FILE *outfile;
    char *arg_ptr = NULL;
    struct geopm_policy_c *policy = NULL;

    const char *usage = "   geopmpolicy --version | --help\n"
                        "   geopmpolicy -c -f output -m mode -d key0:value0,key1:value1...\n"
                        "   geopmpolicy -e (-f input | -m mode -d key0:value0,key1:value1...)\n"
                        "   geopmpolicy -s [-f output]\n"
                        "   geopmpolicy -r [-f input]\n"
                        "   geopmpolicy -w [-f output]\n"
                        "\n"
                        "   --version\n"
                        "      Print version of geopm to standard file, then exit.\n"
                        "\n"
                        "   --help\n"
                        "       Print  brief   summary  of   the  command   line  usage\n"
                        "       information, then exit.\n"
                        "\n"
                        "   -c\n"
                        "       Create a geopm(3) configuration file, -f must be specified\n"
                        "       when using this option which gives the path to the output\n"
                        "       configuration file.\n"
                        "\n"
                        "   -e\n"
                        "       Enforce a static power mode, this mode can be specified\n"
                        "       with the -m and -d options or the -f option.\n"
                        "\n"
                        "   -s\n"
                        "       Create an in MSR save state file for all MSR values that\n"
                        "       geopm(3)  may modify.  The file file can be specified\n"
                        "       with -f.\n"
                        "\n"
                        "   -r\n"
                        "       Restore the MSR values that are recorded in an existing\n"
                        "       MSR save state file.  The input file can be  specified\n"
                        "       with the -f option.\n"
                        "\n"
                        "   -w\n"
                        "       Create a Linux msr driver whitelist file for the current\n"
                        "       platform, -f must  be  specified when using this option which\n"
                        "       gives the path to the output whitelist file.\n"
                        "\n"
                        "   -m mode\n"
                        "       Power management mode, must be one of those described\n"
                        "       in the MODES section of geopmpolicy(3). The static modes do not\n"
                        "       require the geopm runtime to be running concurrently\n"
                        "       with the primary computational application, where as\n"
                        "       dynamic modes do have a runtime requirement on geopm.\n"
                        "\n"
                        "   -d key0:value0,key1:value1...\n"
                        "       Specifies a dictionary of key value pairs which modify\n"
                        "       the behavior of a mode. The key and value options for each\n"
                        "       mode are described in the MODES sections of geopmpolicy(3).\n"
                        "\n"
                        "   -f file_path\n"
                        "       When used with -c or -s file_path is an file file.  When\n"
                        "       used with -e or -r file_path is an file file.  This is a\n"
                        "       geopm(3) configuration file when used with -c or -e and an\n"
                        "       MSR save state file when used with -s or -r.\n"
                        "\n"
                        "     Copyright (C) 2015, 2016, Intel Corporation. All rights reserved.\n"
                        "\n";

    if (argc < 2) {
        fprintf(stderr, "Error: No arguments specified\n");
        fprintf(stderr, usage, argv[0]);
        return EINVAL;
    }
    if (strncmp(argv[1], "--version", strlen("--version") + 1) == 0) {
        printf("%s\n",geopm_version());
        printf("\n\nCopyright (C) 2015, 2016, Intel Corporation. All rights reserved.\n\n");
        return 0;
    }
    if (strncmp(argv[1], "--help", strlen("--help") + 1) == 0) {
        printf("%s\n",usage);
        return 0;
    }

    while (!err && (opt = getopt(argc, argv, "hcesrwm:d:f:")) != -1) {
        arg_ptr = NULL;
        switch (opt) {
            case 'c':
                exec_mode = GEOPMPOLICY_EXEC_MODE_CREATE;
                break;
            case 'e':
                exec_mode = GEOPMPOLICY_EXEC_MODE_ENFORCE;
                break;
            case 's':
                exec_mode = GEOPMPOLICY_EXEC_MODE_SAVE;
                break;
            case 'r':
                exec_mode = GEOPMPOLICY_EXEC_MODE_RESTORE;
                break;
            case 'w':
                exec_mode = GEOPMPOLICY_EXEC_MODE_WHITELIST;
                break;
            case 'm':
                arg_ptr = mode_string;
                break;
            case 'd':
                arg_ptr = option_string;
                break;
            case 'f':
                arg_ptr = file;
                break;
            case 'h':
                printf("%s\n",usage);
                return 0;
            default:
                fprintf(stderr, "Error: unknown parameter \"%c\"\n", opt);
                fprintf(stderr, usage, argv[0]);
                err = EINVAL;
                break;
        }
        if (!err && optarg != NULL) {
            strncpy(arg_ptr, optarg, GEOPMPOLICY_STRING_LENGTH);
            if (arg_ptr[GEOPMPOLICY_STRING_LENGTH - 1] != '\0') {
                fprintf(stderr, "Error: option string too long\n");
                err = EINVAL;
            }
        }
    }

    if (!err && optind != argc) {
        fprintf(stderr, "Error: %s does not take positional arguments\n", argv[0]);
        fprintf(stderr, usage, argv[0]);
        err = EINVAL;
    }

    if (!err && (exec_mode == GEOPMPOLICY_EXEC_MODE_CREATE &&
                 (strlen(mode_string) == 0 || strlen(option_string) == 0))) {
        fprintf(stderr, "Error: In execute mode create, -m and -d are not optional\n");
        err = EINVAL;
    }

    if (!err && (exec_mode == GEOPMPOLICY_EXEC_MODE_ENFORCE && strlen(file) == 0 &&
                 (strlen(mode_string) == 0 || strlen(option_string) == 0))) {
        fprintf(stderr, "Error: In execute mode enforce, either -i or -m and -d must be specified\n");
        err = EINVAL;
    }

    if (!err && exec_mode == GEOPMPOLICY_EXEC_MODE_ENFORCE && strlen(file) > 0) {
        infile = fopen(file, "r");
        if (infile == NULL) {
            fprintf(stderr, "Error: Cannot open specified file for reading: %s\n", file);
            err = EINVAL;
        }
        else {
            fclose(infile);
        }
    }

    if (!err && exec_mode == GEOPMPOLICY_EXEC_MODE_RESTORE) {
        if(strlen(file) == 0) {
            snprintf(file, GEOPMPOLICY_STRING_LENGTH, "/tmp/.geopm_msr_restore.log");
        }
        else {
            //Make sure we are using tempfs to keep these files local to the machine
            if (strncmp(file, "/tmp/", 5)) {
                if (strlen(file) > (GEOPMPOLICY_STRING_LENGTH - strlen("/tmp/"))) {
                    fprintf(stderr, "Error: Specified file path too long\n");
                    err = EINVAL;
                }
                if (!err) {
                    if (file[0] == '/') {
                        snprintf(copy_string, GEOPMPOLICY_STRING_LENGTH, "/tmp%s", file);
                        strncpy(file, copy_string, GEOPMPOLICY_STRING_LENGTH);
                    }
                    else {
                        snprintf(copy_string, GEOPMPOLICY_STRING_LENGTH, "/tmp/%s", file);
                        strncpy(file, copy_string, GEOPMPOLICY_STRING_LENGTH);
                    }
                }
            }
        }
        infile = fopen(file, "r");
        if (infile == NULL) {
            fprintf(stderr, "Error: Cannot open file for reading: %s\n", file);
            err = EINVAL;
        }
        else {
            fclose(infile);
        }
    }


    if (!err && exec_mode == GEOPMPOLICY_EXEC_MODE_CREATE) {
        outfile = fopen(file, "w");
        if (outfile == NULL) {
            fprintf(stderr, "Error: Cannot open specified file for writing: %s\n", file);
            err = EINVAL;
        }
        else {
            fclose(outfile);
        }
    }

    if (!err && exec_mode == GEOPMPOLICY_EXEC_MODE_SAVE) {
        struct stat statbuffer;
        char* pdir;

        if(strlen(file) == 0) {
            snprintf(file, GEOPMPOLICY_STRING_LENGTH, "/tmp/.geopm_msr_restore.log");
        }
        else {
            //Make sure we are using tempfs to keep these files local to the machine
            if (strncmp(file, "/tmp/", 5)) {
                if (strlen(file) > (GEOPMPOLICY_STRING_LENGTH - strlen("/tmp/"))) {
                    fprintf(stderr, "Error: Specified file path too long\n");
                    err = EINVAL;
                }
                if (!err) {
                    if (file[0] == '/') {
                        snprintf(copy_string, GEOPMPOLICY_STRING_LENGTH, "/tmp%s", file);
                        strncpy(file, copy_string, GEOPMPOLICY_STRING_LENGTH);
                    }
                    else {
                        printf("file = %s\n",file);
                        snprintf(copy_string, GEOPMPOLICY_STRING_LENGTH, "/tmp/%s", file);
                        strncpy(file, copy_string, GEOPMPOLICY_STRING_LENGTH);
                        printf("file = %s\n",file);
                    }
                }
            }
        }
        //make sure path exists, if not, create
        pdir = dirname(copy_string);
        for(int i = 1; i < strlen(pdir); i++) {
            if (pdir[i] == '/') {
                pdir[i] = 0;
                if(stat(pdir, &statbuffer) == -1) {
                    if(mkdir(pdir, S_IRWXU)) {
                        fprintf(stderr, "Error: Could not create directory %s\n", dirname(file));
                        return errno ? errno : GEOPM_ERROR_RUNTIME;
                    }
                }
                pdir[i] = '/';
            }
        }
        if(stat(pdir, &statbuffer) == -1) {
            if(mkdir(pdir, S_IRWXU)) {
                fprintf(stderr, "Error: Could not create directory %s\n", dirname(file));
                return errno ? errno : GEOPM_ERROR_RUNTIME;
            }
        }
        outfile = fopen(file, "w");
        if (outfile == NULL) {
            fprintf(stderr, "Error: Cannot open file for writing: %s\n", file);
            err = EINVAL;
        }
        else {
            fclose(outfile);
        }
    }

    if (!err) {
        FILE *fd;
        switch (exec_mode) {
            case GEOPMPOLICY_EXEC_MODE_CREATE:
                err = geopm_policy_create("", file, &policy);
                if (!err) {
                    err = _geopm_policy_mode_parse(policy, mode_string);
                }
                if (!err) {
                    err = _geopm_policy_dict_parse(policy, option_string);
                }
                if (!err) {
                    err = geopm_policy_write(policy);
                }
                if (policy) {
                    (void) geopm_policy_destroy(policy);
                }
                break;
            case GEOPMPOLICY_EXEC_MODE_ENFORCE:
                if (strlen(file) == 0) {
                    err = geopm_policy_create("", "/tmp/geopmpolicy_tmp", &policy);
                    if (!err) {
                        err = _geopm_policy_mode_parse(policy, mode_string);
                    }
                    if (!err) {
                        err = _geopm_policy_dict_parse(policy, option_string);
                    }
                }
                else {
                    err = geopm_policy_create(file, "", &policy);
                }
                if (!err) {
                    err = geopm_policy_enforce_static(policy);
                }
                if (policy) {
                    (void) geopm_policy_destroy(policy);
                }
                break;
            case GEOPMPOLICY_EXEC_MODE_SAVE:
                err = geopm_platform_msr_save(file);
                break;
            case GEOPMPOLICY_EXEC_MODE_RESTORE:
                err = geopm_platform_msr_restore(file);
                break;
            case GEOPMPOLICY_EXEC_MODE_WHITELIST:
                if (strlen(file) == 0) {
                    fd = stdout;
                }
                else {
                    fd = fopen(file, "w");
                    if (fd == NULL) {
                        err = errno ? errno : GEOPM_ERROR_RUNTIME;
                    }
                }
                if (!err) {
                    err = geopm_platform_msr_whitelist(fd);
                    fclose(fd);
                }
                break;
            default:
                fprintf(stderr, "Error: Invalid execution mode.\n");
                err = EINVAL;
                break;
        };
    }

    if (err) {
        geopm_error_message(err, error_string, GEOPMPOLICY_STRING_LENGTH);
        fprintf(stderr, "Error: %s.\n", error_string);
    }
    return err;
}