int pqos_cap_get_event(const struct pqos_cap *cap, const enum pqos_mon_event event, const struct pqos_monitor **p_mon) { const struct pqos_capability *cap_item = NULL; const struct pqos_cap_mon *mon = NULL; int ret = PQOS_RETVAL_OK; unsigned i; if (cap == NULL || p_mon == NULL) return PQOS_RETVAL_PARAM; ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MON, &cap_item); if (ret != PQOS_RETVAL_OK) return ret; ASSERT(cap_item != NULL); mon = cap_item->u.mon; ret = PQOS_RETVAL_ERROR; for (i = 0; i < mon->num_events; i++) { if (mon->events[i].type == event) { *p_mon = &mon->events[i]; ret = PQOS_RETVAL_OK; break; } } return ret; }
int main(int argc, char *argv[]) { struct pqos_config cfg; const struct pqos_cpuinfo *p_cpu = NULL; const struct pqos_cap *p_cap = NULL; const struct pqos_capability *cap_l3ca = NULL; unsigned sock_count, *sockets = NULL; int ret, exit_val = EXIT_SUCCESS; memset(&cfg, 0, sizeof(cfg)); cfg.fd_log = STDOUT_FILENO; cfg.verbose = 0; /* PQoS Initialization - Check and initialize CAT and CMT capability */ ret = pqos_init(&cfg); if (ret != PQOS_RETVAL_OK) { printf("Error initializing PQoS library!\n"); exit_val = EXIT_FAILURE; goto error_exit; } /* Get CMT capability and CPU info pointer */ ret = pqos_cap_get(&p_cap, &p_cpu); if (ret != PQOS_RETVAL_OK) { printf("Error retrieving PQoS capabilities!\n"); exit_val = EXIT_FAILURE; goto error_exit; } if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-H"))) { printf("Usage: %s\n\n", argv[0]); goto error_exit; } /* Reset Api */ ret = pqos_alloc_reset(PQOS_REQUIRE_CDP_ANY, PQOS_REQUIRE_CDP_ANY, PQOS_MBA_ANY); if (ret != PQOS_RETVAL_OK) printf("CAT reset failed!\n"); else printf("CAT reset successful\n"); /* Get CPU socket information to set COS */ sockets = pqos_cpu_get_sockets(p_cpu, &sock_count); if (sockets == NULL) { printf("Error retrieving CPU socket information!\n"); exit_val = EXIT_FAILURE; goto error_exit; } (void) pqos_cap_get_type(p_cap, PQOS_CAP_TYPE_L3CA, &cap_l3ca); /* Print COS and associated cores */ print_allocation_config(cap_l3ca, sock_count, sockets, p_cpu); error_exit: /* reset and deallocate all the resources */ ret = pqos_fini(); if (ret != PQOS_RETVAL_OK) printf("Error shutting down PQoS library!\n"); if (sockets != NULL) free(sockets); return exit_val; }
int main(int argc, char *argv[]) { struct pqos_config config; const struct pqos_cpuinfo *p_cpu = NULL; const struct pqos_cap *p_cap = NULL; int ret, exit_val = EXIT_SUCCESS; const struct pqos_capability *cap_mon = NULL; memset(&config, 0, sizeof(config)); config.fd_log = STDOUT_FILENO; config.verbose = 0; /* PQoS Initialization - Check and initialize CAT and CMT capability */ ret = pqos_init(&config); if (ret != PQOS_RETVAL_OK) { printf("Error initializing PQoS library!\n"); exit_val = EXIT_FAILURE; goto error_exit; } /* Get CMT capability and CPU info pointer */ ret = pqos_cap_get(&p_cap, &p_cpu); if (ret != PQOS_RETVAL_OK) { printf("Error retrieving PQoS capabilities!\n"); exit_val = EXIT_FAILURE; goto error_exit; } /* Get input from user */ monitoring_get_input(argc, argv); (void) pqos_cap_get_type(p_cap, PQOS_CAP_TYPE_MON, &cap_mon); /* Setup the monitoring resources */ ret = setup_monitoring(p_cpu, cap_mon); if (ret != PQOS_RETVAL_OK) { printf("Error Setting up monitoring!\n"); exit_val = EXIT_FAILURE; goto error_exit; } /* Start Monitoring */ monitoring_loop(); /* Stop Monitoring */ stop_monitoring(); error_exit: ret = pqos_fini(); if (ret != PQOS_RETVAL_OK) printf("Error shutting down PQoS library!\n"); return exit_val; }
int pqos_l3ca_get_cos_num(const struct pqos_cap *cap, unsigned *cos_num) { const struct pqos_capability *item = NULL; int ret = PQOS_RETVAL_OK; ASSERT(cap != NULL && cos_num != NULL); if (cap == NULL || cos_num == NULL) return PQOS_RETVAL_PARAM; ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L3CA, &item); if (ret != PQOS_RETVAL_OK) return ret; /**< no L3CA capability */ ASSERT(item != NULL); *cos_num = item->u.l3ca->num_classes; return ret; }
int pqos_l3ca_cdp_enabled(const struct pqos_cap *cap, int *cdp_supported, int *cdp_enabled) { const struct pqos_capability *item = NULL; int ret = PQOS_RETVAL_OK; ASSERT(cap != NULL && (cdp_enabled != NULL || cdp_supported != NULL)); if (cap == NULL || (cdp_enabled == NULL && cdp_supported == NULL)) return PQOS_RETVAL_PARAM; ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L3CA, &item); if (ret != PQOS_RETVAL_OK) return ret; /**< no L3CA capability */ ASSERT(item != NULL); if (cdp_supported != NULL) *cdp_supported = item->u.l3ca->cdp; if (cdp_enabled != NULL) *cdp_enabled = item->u.l3ca->cdp_on; return ret; }
/** * @brief Allocates RMID for given \a event * * @param [in] cluster CPU cluster id * @param [in] event Monitoring event type * @param [out] rmid resource monitoring id * * @return Operations status */ static int rmid_alloc(const unsigned cluster, const enum pqos_mon_event event, pqos_rmid_t *rmid) { enum rmid_state *rmid_table = NULL; const struct pqos_capability *item = NULL; const struct pqos_cap_mon *mon = NULL; int ret = PQOS_RETVAL_OK; unsigned max_rmid = 0; unsigned i; int j; unsigned mask_found = 0; if (rmid == NULL) return PQOS_RETVAL_PARAM; ret = mon_rmid_alloc_param_check(cluster, &rmid_table); if (ret != PQOS_RETVAL_OK) return ret; ASSERT(rmid_table != NULL); /** * This is not so straight forward as it appears to be. * We first have to figure out max RMID * for given event type. In order to do so we need: * - go through capabilities structure * - find monitoring capability * - look for the \a event in the event list * - find max RMID matching the \a event */ ASSERT(m_cap != NULL); ret = pqos_cap_get_type(m_cap, PQOS_CAP_TYPE_MON, &item); if (ret != PQOS_RETVAL_OK) return ret; ASSERT(item != NULL); mon = item->u.mon; /* Find which events are supported */ max_rmid = m_rmid_max; for (i = 0; i < mon->num_events; i++) { if (event & mon->events[i].type) { mask_found |= mon->events[i].type; max_rmid = (max_rmid > mon->events[i].max_rmid) ? mon->events[i].max_rmid : max_rmid; } } /** * Check if all of the events are supported */ if (event != mask_found || max_rmid == 0) return PQOS_RETVAL_ERROR; ASSERT(m_rmid_max >= max_rmid); /** * Check for free RMID in the table * Do it backwards (from max to 0) in order to preserve low RMID values * for overlapping RMID ranges for future events. */ ret = PQOS_RETVAL_ERROR; for (j = (int)max_rmid-1; j >= 0; j--) { if (rmid_table[j] != RMID_STATE_FREE) continue; rmid_table[j] = RMID_STATE_ALLOCATED; *rmid = (pqos_rmid_t) j; ret = PQOS_RETVAL_OK; break; } return ret; }
int pqos_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap, const struct pqos_config *cfg) { const struct pqos_capability *item = NULL; unsigned i = 0, fails = 0; int ret = PQOS_RETVAL_OK; m_cpu = cpu; m_cap = cap; #ifndef PQOS_NO_PID_API /** * Init monitoring processes */ ret = pqos_pid_init(m_cap); if (ret == PQOS_RETVAL_ERROR) return ret; #endif /* PQOS_NO_PID_API */ /** * If monitoring capability has been discovered * then get max RMID supported by a CPU socket * and allocate memory for RMID table */ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MON, &item); if (ret != PQOS_RETVAL_OK) return ret; m_num_clusters = cpu_get_num_clusters(m_cpu); ASSERT(m_num_clusters >= 1); ASSERT(item != NULL); m_rmid_max = item->u.mon->max_rmid; if (m_rmid_max == 0) { pqos_mon_fini(); return PQOS_RETVAL_PARAM; } LOG_DEBUG("Max RMID per monitoring cluster is %u\n", m_rmid_max); ASSERT(m_cpu != NULL); m_dim_cores = cpu_get_num_cores(m_cpu); m_core_map = (struct mon_entry *)malloc(m_dim_cores * sizeof(m_core_map[0])); ASSERT(m_core_map != NULL); if (m_core_map == NULL) { pqos_mon_fini(); return PQOS_RETVAL_ERROR; } memset(m_core_map, 0, m_dim_cores*sizeof(m_core_map[0])); m_rmid_cluster_map = (enum rmid_state **)malloc(m_num_clusters * sizeof(m_rmid_cluster_map[0])); ASSERT(m_rmid_cluster_map != NULL); if (m_rmid_cluster_map == NULL) { pqos_mon_fini(); return PQOS_RETVAL_ERROR; } for (i = 0 ; i < m_num_clusters; i++) { const size_t size = m_rmid_max * sizeof(enum rmid_state); enum rmid_state *st = (enum rmid_state *)malloc(size); if (st == NULL) { pqos_mon_fini(); return PQOS_RETVAL_RESOURCE; } m_rmid_cluster_map[i] = st; memset(st, 0, size); st[RMID0] = RMID_STATE_UNAVAILABLE; /**< RMID0 has a special meaning */ } LOG_DEBUG("RMID internal tables allocated\n"); m_force_mon = cfg->free_in_use_rmid; /** * Read current core<=>RMID associations */ for (i = 0; i < m_cpu->num_cores; i++) { pqos_rmid_t rmid = 0; unsigned coreid = m_cpu->cores[i].lcore; unsigned clusterid = m_cpu->cores[i].cluster; ret = mon_assoc_get(coreid, &rmid); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("Failed to read RMID association of " "lcore %u!\n", coreid); fails++; } else { ASSERT(rmid < m_rmid_max); m_core_map[coreid].rmid = rmid; m_core_map[coreid].unavailable = 0; m_core_map[coreid].grp = NULL; if (rmid == RMID0) continue; /** * At this stage we know core is assigned to non-zero RMID * This means it may be used by another instance of * the program for monitoring. * The other option is that previously ran program * died and it didn't revert RMID association. */ if (!cfg->free_in_use_rmid) { enum rmid_state *pstate = NULL; LOG_DEBUG("Detected RMID%u is associated with " "core %u. " "Marking RMID & core unavailable.\n", rmid, coreid); ASSERT(clusterid < m_num_clusters); pstate = m_rmid_cluster_map[clusterid]; pstate[rmid] = RMID_STATE_UNAVAILABLE; m_core_map[coreid].unavailable = 1; } else { LOG_DEBUG("Detected RMID%u is associated with " "core %u. " "Freeing the RMID and associating " "core with RMID0.\n", rmid, coreid); ret = mon_assoc_set_nocheck(coreid, RMID0); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("Failed to associate core %u " "with RMID0!\n", coreid); fails++; } } } } ret = (fails == 0) ? PQOS_RETVAL_OK : PQOS_RETVAL_ERROR; if (ret != PQOS_RETVAL_OK) pqos_mon_fini(); return ret; }
static int rdt_preinit(void) { int ret; if (g_rdt != NULL) { /* already initialized if config callback was called before init callback */ return 0; } g_rdt = calloc(1, sizeof(*g_rdt)); if (g_rdt == NULL) { ERROR(RDT_PLUGIN ": Failed to allocate memory for rdt context."); return -ENOMEM; } struct pqos_config pqos = {.fd_log = -1, .callback_log = rdt_pqos_log, .context_log = NULL, .verbose = 0}; ret = pqos_init(&pqos); if (ret != PQOS_RETVAL_OK) { ERROR(RDT_PLUGIN ": Error initializing PQoS library!"); goto rdt_preinit_error1; } ret = pqos_cap_get(&g_rdt->pqos_cap, &g_rdt->pqos_cpu); if (ret != PQOS_RETVAL_OK) { ERROR(RDT_PLUGIN ": Error retrieving PQoS capabilities."); goto rdt_preinit_error2; } ret = pqos_cap_get_type(g_rdt->pqos_cap, PQOS_CAP_TYPE_MON, &g_rdt->cap_mon); if (ret == PQOS_RETVAL_PARAM) { ERROR(RDT_PLUGIN ": Error retrieving monitoring capabilities."); goto rdt_preinit_error2; } if (g_rdt->cap_mon == NULL) { ERROR( RDT_PLUGIN ": Monitoring capability not detected. Nothing to do for the plugin."); goto rdt_preinit_error2; } /* Reset pqos monitoring groups registers */ pqos_mon_reset(); return 0; rdt_preinit_error2: pqos_fini(); rdt_preinit_error1: sfree(g_rdt); return -1; } static int rdt_config(oconfig_item_t *ci) { if (rdt_preinit() != 0) { g_state = CONFIGURATION_ERROR; /* if we return -1 at this point collectd reports a failure in configuration and aborts */ return (0); } for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; if (strcasecmp("Cores", child->key) == 0) { if (rdt_config_cgroups(child) != 0) { g_state = CONFIGURATION_ERROR; /* if we return -1 at this point collectd reports a failure in configuration and aborts */ return (0); } #if COLLECT_DEBUG rdt_dump_cgroups(); #endif /* COLLECT_DEBUG */ } else { ERROR(RDT_PLUGIN ": Unknown configuration parameter \"%s\".", child->key); } } return 0; } static void rdt_submit_derive(const char *cgroup, const char *type, const char *type_instance, derive_t value) { value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t){.derive = value}; vl.values_len = 1; sstrncpy(vl.plugin, RDT_PLUGIN, sizeof(vl.plugin)); snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s", cgroup); sstrncpy(vl.type, type, sizeof(vl.type)); if (type_instance) sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); plugin_dispatch_values(&vl); }
int pqos_l3ca_reset(const struct pqos_cap *cap, const struct pqos_cpuinfo *cpu) { unsigned *sockets = NULL; unsigned sockets_num = 0, sockets_num_ret = 0; const struct pqos_capability *item = NULL; int ret = PQOS_RETVAL_OK; unsigned j; ASSERT(cap != NULL && cpu != NULL); if (cap == NULL || cpu == NULL) return PQOS_RETVAL_PARAM; ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L3CA, &item); if (ret != PQOS_RETVAL_OK) return ret; /**< no L3CA capability */ ASSERT(item != NULL); /** * Figure out number of sockets in the system * - allocate enough memory to accommodate all socket id's * - use stack frame allocator for it (not heap) * - get list of socket id's through another API * - validate that number of socket id's obtained in * two different ways match */ sockets_num = __get_num_sockets(cpu); if (sockets_num == 0) return PQOS_RETVAL_RESOURCE; sockets = alloca(sockets_num * sizeof(sockets[0])); if (sockets == NULL) return PQOS_RETVAL_RESOURCE; ret = pqos_cpu_get_sockets(cpu, sockets_num, &sockets_num_ret, sockets); if (ret != PQOS_RETVAL_OK) return ret; ASSERT(sockets_num_ret == sockets_num); if (sockets_num != sockets_num_ret) return PQOS_RETVAL_ERROR; /** * Change COS definition on all sockets * so that each COS allows for access to all cache ways */ for (j = 0; j < sockets_num; j++) { const uint64_t ways_mask = (1ULL<<item->u.l3ca->num_ways)-1ULL; unsigned i; for (i = 0; i < item->u.l3ca->num_classes; i++) { struct pqos_l3ca cos; cos.cdp = 0; cos.class_id = i; cos.ways_mask = ways_mask; ret = pqos_l3ca_set(sockets[j], 1, &cos); if (ret != PQOS_RETVAL_OK) return ret; } } /** * Associate all cores with COS0 */ for (j = 0; j < cpu->num_cores; j++) { ret = pqos_l3ca_assoc_set(cpu->cores[j].lcore, 0); if (ret != PQOS_RETVAL_OK) return ret; } return ret; }
int main(int argc, char **argv) { struct pqos_config cfg; const struct pqos_cpuinfo *p_cpu = NULL; const struct pqos_cap *p_cap = NULL; const struct pqos_capability *cap_mon = NULL, *cap_l3ca = NULL; unsigned sock_count, sockets[PQOS_MAX_SOCKETS]; int cmd, ret, exit_val = EXIT_SUCCESS; int opt_index = 0; m_cmd_name = argv[0]; print_warning(); while ((cmd = getopt_long(argc, argv, "Hhf:i:m:Tt:l:o:u:e:c:a:p:S:srvVR", long_cmd_opts, &opt_index)) != -1) { switch (cmd) { case 'h': print_help(1); return EXIT_SUCCESS; case 'H': profile_l3ca_list(stdout); return EXIT_SUCCESS; case 'S': selfn_set_config(optarg); break; case 'f': if (sel_config_file != NULL) { printf("Only one config file argument is " "accepted!\n"); return EXIT_FAILURE; } selfn_strdup(&sel_config_file, optarg); parse_config_file(sel_config_file); break; case 'i': selfn_monitor_interval(optarg); break; case 'p': selfn_monitor_pids(optarg); break; case 'm': selfn_monitor_cores(optarg); break; case 't': selfn_monitor_time(optarg); break; case 'T': selfn_monitor_top_like(NULL); break; case 'l': selfn_log_file(optarg); break; case 'o': selfn_monitor_file(optarg); break; case 'u': selfn_monitor_file_type(optarg); break; case 'e': selfn_allocation_class(optarg); break; case 'r': sel_free_in_use_rmid = 1; break; case 'R': selfn_reset_cat(NULL); break; case 'a': selfn_allocation_assoc(optarg); break; case 'c': selfn_allocation_select(optarg); break; case 's': selfn_show_allocation(NULL); break; case 'v': selfn_verbose_mode(NULL); break; case 'V': selfn_super_verbose_mode(NULL); break; default: printf("Unsupported option: -%c. " "See option -h for help.\n", optopt); return EXIT_FAILURE; break; case '?': print_help(0); return EXIT_SUCCESS; break; } } memset(&cfg, 0, sizeof(cfg)); cfg.verbose = sel_verbose_mode; cfg.free_in_use_rmid = sel_free_in_use_rmid; cfg.cdp_cfg = selfn_cdp_config; /** * Set up file descriptor for message log */ if (sel_log_file == NULL) { cfg.fd_log = STDOUT_FILENO; } else { cfg.fd_log = open(sel_log_file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); if (cfg.fd_log == -1) { printf("Error opening %s log file!\n", sel_log_file); exit_val = EXIT_FAILURE; goto error_exit_2; } } ret = pqos_init(&cfg); if (ret != PQOS_RETVAL_OK) { printf("Error initializing PQoS library!\n"); exit_val = EXIT_FAILURE; goto error_exit_1; } ret = pqos_cap_get(&p_cap, &p_cpu); if (ret != PQOS_RETVAL_OK) { printf("Error retrieving PQoS capabilities!\n"); exit_val = EXIT_FAILURE; goto error_exit_2; } ret = pqos_cpu_get_sockets(p_cpu, PQOS_MAX_SOCKETS, &sock_count, sockets); if (ret != PQOS_RETVAL_OK) { printf("Error retrieving CPU socket information!\n"); exit_val = EXIT_FAILURE; goto error_exit_2; } ret = pqos_cap_get_type(p_cap, PQOS_CAP_TYPE_MON, &cap_mon); if (ret == PQOS_RETVAL_PARAM) { printf("Error retrieving monitoring capabilities!\n"); exit_val = EXIT_FAILURE; goto error_exit_2; } ret = pqos_cap_get_type(p_cap, PQOS_CAP_TYPE_L3CA, &cap_l3ca); if (ret == PQOS_RETVAL_PARAM) { printf("Error retrieving allocation capabilities!\n"); exit_val = EXIT_FAILURE; goto error_exit_2; } if (sel_reset_CAT) { /** * Reset CAT configuration to after-reset state and exit */ if (pqos_l3ca_reset(p_cap, p_cpu) != PQOS_RETVAL_OK) { exit_val = EXIT_FAILURE; printf("CAT reset failed!\n"); } else printf("CAT reset successful\n"); goto allocation_exit; } if (sel_show_allocation_config) { /** * Show info about allocation config and exit */ alloc_print_config(cap_mon, cap_l3ca, sock_count, sockets, p_cpu); goto allocation_exit; } if (sel_allocation_profile != NULL) { if (profile_l3ca_apply(sel_allocation_profile, cap_l3ca) != 0) { exit_val = EXIT_FAILURE; goto error_exit_2; } } switch (alloc_apply(cap_l3ca, sock_count, sockets)) { case 0: /* nothing to apply */ break; case 1: /* new allocation config applied and all is good */ goto allocation_exit; break; case -1: /* something went wrong */ default: exit_val = EXIT_FAILURE; goto error_exit_2; break; } /** * Just monitoring option left on the table now */ if (cap_mon == NULL) { printf("Monitoring capability not detected!\n"); exit_val = EXIT_FAILURE; goto error_exit_2; } if (monitor_setup(p_cpu, cap_mon) != 0) { exit_val = EXIT_FAILURE; goto error_exit_2; } monitor_loop(p_cap); monitor_stop(); allocation_exit: error_exit_2: ret = pqos_fini(); ASSERT(ret == PQOS_RETVAL_OK); if (ret != PQOS_RETVAL_OK) printf("Error shutting down PQoS library!\n"); error_exit_1: monitor_cleanup(); /** * Close file descriptor for message log */ if (cfg.fd_log > 0 && cfg.fd_log != STDOUT_FILENO) close(cfg.fd_log); /** * Free allocated memory */ if (sel_allocation_profile != NULL) free(sel_allocation_profile); if (sel_log_file != NULL) free(sel_log_file); if (sel_config_file != NULL) free(sel_config_file); return exit_val; }
static int rdt_preinit(void) { int ret; if (g_rdt != NULL) { /* already initialized if config callback was called before init callback */ return (0); } g_rdt = calloc(1, sizeof(*g_rdt)); if (g_rdt == NULL) { ERROR(RDT_PLUGIN ": Failed to allocate memory for rdt context."); return (-ENOMEM); } struct pqos_config pqos = {.fd_log = -1, .callback_log = rdt_pqos_log, .context_log = NULL, .verbose = 0}; ret = pqos_init(&pqos); if (ret != PQOS_RETVAL_OK) { ERROR(RDT_PLUGIN ": Error initializing PQoS library!"); goto rdt_preinit_error1; } ret = pqos_cap_get(&g_rdt->pqos_cap, &g_rdt->pqos_cpu); if (ret != PQOS_RETVAL_OK) { ERROR(RDT_PLUGIN ": Error retrieving PQoS capabilities."); goto rdt_preinit_error2; } ret = pqos_cap_get_type(g_rdt->pqos_cap, PQOS_CAP_TYPE_MON, &g_rdt->cap_mon); if (ret == PQOS_RETVAL_PARAM) { ERROR(RDT_PLUGIN ": Error retrieving monitoring capabilities."); goto rdt_preinit_error2; } if (g_rdt->cap_mon == NULL) { ERROR( RDT_PLUGIN ": Monitoring capability not detected. Nothing to do for the plugin."); goto rdt_preinit_error2; } /* Reset pqos monitoring groups registers */ pqos_mon_reset(); return (0); rdt_preinit_error2: pqos_fini(); rdt_preinit_error1: sfree(g_rdt); return (-1); } static int rdt_config(oconfig_item_t *ci) { int ret = 0; ret = rdt_preinit(); if (ret != 0) { g_state = CONFIGURATION_ERROR; /* if we return -1 at this point collectd reports a failure in configuration and aborts */ goto exit; } for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; if (strcasecmp("Cores", child->key) == 0) { ret = rdt_config_cgroups(child); if (ret != 0) { g_state = CONFIGURATION_ERROR; /* if we return -1 at this point collectd reports a failure in configuration and aborts */ goto exit; } #if COLLECT_DEBUG rdt_dump_cgroups(); #endif /* COLLECT_DEBUG */ } else { ERROR(RDT_PLUGIN ": Unknown configuration parameter \"%s\".", child->key); } } exit: return (0); }
int hw_alloc_reset(const enum pqos_cdp_config l3_cdp_cfg) { unsigned *sockets = NULL; unsigned sockets_num = 0; unsigned *l2ids = NULL; unsigned l2id_num = 0; const struct pqos_capability *alloc_cap = NULL; const struct pqos_cap_l3ca *l3_cap = NULL; const struct pqos_cap_l2ca *l2_cap = NULL; const struct pqos_cap_mba *mba_cap = NULL; int ret = PQOS_RETVAL_OK; unsigned max_l3_cos = 0; unsigned j; if (l3_cdp_cfg != PQOS_REQUIRE_CDP_ON && l3_cdp_cfg != PQOS_REQUIRE_CDP_OFF && l3_cdp_cfg != PQOS_REQUIRE_CDP_ANY) { LOG_ERROR("Unrecognized L3 CDP configuration setting %d!\n", l3_cdp_cfg); return PQOS_RETVAL_PARAM; } /* Get L3 CAT capabilities */ (void) pqos_cap_get_type(m_cap, PQOS_CAP_TYPE_L3CA, &alloc_cap); if (alloc_cap != NULL) l3_cap = alloc_cap->u.l3ca; /* Get L2 CAT capabilities */ alloc_cap = NULL; (void) pqos_cap_get_type(m_cap, PQOS_CAP_TYPE_L2CA, &alloc_cap); if (alloc_cap != NULL) l2_cap = alloc_cap->u.l2ca; /* Get MBA capabilities */ alloc_cap = NULL; (void) pqos_cap_get_type(m_cap, PQOS_CAP_TYPE_MBA, &alloc_cap); if (alloc_cap != NULL) mba_cap = alloc_cap->u.mba; /* Check if either L2 CAT, L3 CAT or MBA is supported */ if (l2_cap == NULL && l3_cap == NULL && mba_cap == NULL) { LOG_ERROR("L2 CAT/L3 CAT/MBA not present!\n"); ret = PQOS_RETVAL_RESOURCE; /* no L2/L3 CAT present */ goto pqos_alloc_reset_exit; } /* Check L3 CDP requested while not present */ if (l3_cap == NULL && l3_cdp_cfg != PQOS_REQUIRE_CDP_ANY) { LOG_ERROR("L3 CDP setting requested but no L3 CAT present!\n"); ret = PQOS_RETVAL_RESOURCE; goto pqos_alloc_reset_exit; } if (l3_cap != NULL) { /* Check against erroneous CDP request */ if (l3_cdp_cfg == PQOS_REQUIRE_CDP_ON && !l3_cap->cdp) { LOG_ERROR("CAT/CDP requested but not supported by the " "platform!\n"); ret = PQOS_RETVAL_PARAM; goto pqos_alloc_reset_exit; } /* Get maximum number of L3 CAT classes */ max_l3_cos = l3_cap->num_classes; if (l3_cap->cdp && l3_cap->cdp_on) max_l3_cos = max_l3_cos * 2; } /** * Get number & list of sockets in the system */ sockets = pqos_cpu_get_sockets(m_cpu, &sockets_num); if (sockets == NULL || sockets_num == 0) goto pqos_alloc_reset_exit; if (l3_cap != NULL) { /** * Change L3 COS definition on all sockets * so that each COS allows for access to all cache ways */ for (j = 0; j < sockets_num; j++) { unsigned core = 0; ret = pqos_cpu_get_one_core(m_cpu, sockets[j], &core); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; const uint64_t ways_mask = (1ULL << l3_cap->num_ways) - 1ULL; ret = alloc_cos_reset(PQOS_MSR_L3CA_MASK_START, max_l3_cos, core, ways_mask); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; } } if (l2_cap != NULL) { /** * Get number & list of L2ids in the system * Then go through all L2 ids and reset L2 classes on them */ l2ids = pqos_cpu_get_l2ids(m_cpu, &l2id_num); if (l2ids == NULL || l2id_num == 0) goto pqos_alloc_reset_exit; for (j = 0; j < l2id_num; j++) { const uint64_t ways_mask = (1ULL << l2_cap->num_ways) - 1ULL; unsigned core = 0; ret = pqos_cpu_get_one_by_l2id(m_cpu, l2ids[j], &core); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; ret = alloc_cos_reset(PQOS_MSR_L2CA_MASK_START, l2_cap->num_classes, core, ways_mask); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; } } if (mba_cap != NULL) { /** * Go through all sockets and reset MBA class defintions * 0 is the default MBA COS value in linear mode. */ for (j = 0; j < sockets_num; j++) { unsigned core = 0; ret = pqos_cpu_get_one_core(m_cpu, sockets[j], &core); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; ret = alloc_cos_reset(PQOS_MSR_MBA_MASK_START, mba_cap->num_classes, core, 0); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; } } /** * Associate all cores with COS0 */ ret = alloc_assoc_reset(); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; /** * Turn L3 CDP ON or OFF upon the request */ if (l3_cap != NULL) { if (l3_cdp_cfg == PQOS_REQUIRE_CDP_ON && !l3_cap->cdp_on) { /** * Turn on CDP */ LOG_INFO("Turning CDP ON ...\n"); ret = cdp_enable(sockets_num, sockets, 1); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("CDP enable error!\n"); goto pqos_alloc_reset_exit; } _pqos_cap_l3cdp_change(l3_cap->cdp_on, 1); } if (l3_cdp_cfg == PQOS_REQUIRE_CDP_OFF && l3_cap->cdp_on && l3_cap->cdp) { /** * Turn off CDP */ LOG_INFO("Turning CDP OFF ...\n"); ret = cdp_enable(sockets_num, sockets, 0); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("CDP disable error!\n"); goto pqos_alloc_reset_exit; } _pqos_cap_l3cdp_change(l3_cap->cdp_on, 0); } } pqos_alloc_reset_exit: if (sockets != NULL) free(sockets); if (l2ids != NULL) free(l2ids); return ret; }
int hw_mba_set(const unsigned socket, const unsigned num_cos, const struct pqos_mba *requested, struct pqos_mba *actual) { int ret = PQOS_RETVAL_OK; unsigned i = 0, count = 0, core = 0, step = 0; const struct pqos_capability *mba_cap = NULL; if (requested == NULL || num_cos == 0) return PQOS_RETVAL_PARAM; /** * Check if MBA is supported */ ASSERT(m_cap != NULL); ret = pqos_cap_get_type(m_cap, PQOS_CAP_TYPE_MBA, &mba_cap); if (ret != PQOS_RETVAL_OK) return PQOS_RETVAL_RESOURCE; /* MBA not supported */ count = mba_cap->u.mba->num_classes; step = mba_cap->u.mba->throttle_step; /** * Non-linear mode not currently supported */ if (!mba_cap->u.mba->is_linear) { LOG_ERROR("MBA non-linear mode not currently supported!\n"); return PQOS_RETVAL_RESOURCE; } /** * Check if MBA rate and class * id's are within allowed range. */ for (i = 0; i < num_cos; i++) { if (requested[i].mb_rate == 0 || requested[i].mb_rate > 100) { LOG_ERROR("MBA COS%u rate out of range (from 1-100)!\n", requested[i].class_id); return PQOS_RETVAL_PARAM; } if (requested[i].class_id >= count) { LOG_ERROR("MBA COS%u is out of range (COS%u is max)!\n", requested[i].class_id, count - 1); return PQOS_RETVAL_PARAM; } } ASSERT(m_cpu != NULL); ret = pqos_cpu_get_one_core(m_cpu, socket, &core); if (ret != PQOS_RETVAL_OK) return ret; for (i = 0; i < num_cos; i++) { const uint32_t reg = requested[i].class_id + PQOS_MSR_MBA_MASK_START; uint64_t val = PQOS_MBA_LINEAR_MAX - (((requested[i].mb_rate + (step/2)) / step) * step); int retval = MACHINE_RETVAL_OK; if (val > mba_cap->u.mba->throttle_max) val = mba_cap->u.mba->throttle_max; retval = msr_write(core, reg, val); if (retval != MACHINE_RETVAL_OK) return PQOS_RETVAL_ERROR; /** * If table to store actual values set is passed, * read MSR values and store in table */ if (actual == NULL) continue; retval = msr_read(core, reg, &val); if (retval != MACHINE_RETVAL_OK) return PQOS_RETVAL_ERROR; actual[i] = requested[i]; actual[i].mb_rate = (PQOS_MBA_LINEAR_MAX - val); } return ret; }