int get_pkg_rapl_limit(const unsigned socket, struct rapl_limit *limit1, struct rapl_limit *limit2) { static uint64_t *rapl_flags = NULL; sockets_assert(&socket, __LINE__, __FILE__); if (rapl_flags == NULL) { if (rapl_storage(NULL, &rapl_flags)) { return -1; } } /* Make sure the pkg power limit register exists. */ if (*rapl_flags & PKG_POWER_LIMIT) { if (limit1 != NULL) { read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, &(limit1->bits)); } if (limit2 != NULL) { read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, &(limit2->bits)); } calc_pkg_rapl_limit(socket, limit1, limit2); } else { libmsr_error_handler("get_pkg_rapl_limit(): PKG domain RAPL power limit not supported on this architecture", LIBMSR_ERROR_PLATFORM_NOT_SUPPORTED, getenv("HOSTNAME"), __FILE__, __LINE__); return -1; } return 0; }
int get_rapl_power_info(const unsigned socket, struct rapl_power_info *info) { uint64_t val = 0; static uint64_t *rapl_flags = NULL; sockets_assert(&socket, __LINE__, __FILE__); if (rapl_flags == NULL) { if (rapl_storage(NULL, &rapl_flags)) { libmsr_error_handler("get_rapl_power_info(): Cannot load rapl_flags", LIBMSR_ERROR_RAPL_INIT, getenv("HOSTNAME"), __FILE__, __LINE__); return -1; } } #ifdef LIBMSR_DEBUG fprintf(stderr, "%s %s::%d DEBUG: (get_rapl_power_info)\n", getenv("HOSTNAME"), __FILE__, __LINE__); #endif if (*rapl_flags & PKG_POWER_INFO) { read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_INFO, &(info->msr_pkg_power_info)); val = MASK_VAL(info->msr_pkg_power_info, 54, 48); translate(socket, &val, &(info->pkg_max_window), BITS_TO_SECONDS_STD); val = MASK_VAL(info->msr_pkg_power_info, 46, 32); translate(socket, &val, &(info->pkg_max_power), BITS_TO_WATTS); val = MASK_VAL(info->msr_pkg_power_info, 30, 16); translate(socket, &val, &(info->pkg_min_power), BITS_TO_WATTS); val = MASK_VAL(info->msr_pkg_power_info, 14, 0); translate(socket, &val, &(info->pkg_therm_power), BITS_TO_WATTS); } if (*rapl_flags & DRAM_POWER_INFO) { read_msr_by_coord(socket, 0, 0, MSR_DRAM_POWER_INFO, &(info->msr_dram_power_info)); val = MASK_VAL(info->msr_dram_power_info, 54, 48); translate(socket, &val, &(info->dram_max_window), BITS_TO_SECONDS_STD); val = MASK_VAL(info->msr_dram_power_info, 46, 32); translate(socket, &val, &(info->dram_max_power), BITS_TO_WATTS); val = MASK_VAL(info->msr_dram_power_info, 30, 16); translate(socket, &val, &(info->dram_min_power), BITS_TO_WATTS); val = MASK_VAL(info->msr_dram_power_info, 14, 0); translate(socket, &val, &(info->dram_therm_power), BITS_TO_WATTS); } return 0; }
void set_misc_enable(int package, struct misc_enable *s) { uint64_t msrVal; read_msr_by_coord(package, 0, 0, IA32_MISC_ENABLE, &msrVal); //msrVal = 64; //temp value assert(s->fast_string_enable == 0 || s->fast_string_enable == 1); assert(s->auto_TCC_enable == 0 || s->auto_TCC_enable == 1); assert(s->TM2_enable == 0 || s->TM2_enable == 1); assert(s->enhanced_Intel_SpeedStep_Tech_enable == 0 || s->enhanced_Intel_SpeedStep_Tech_enable == 1); assert(s->limit_CPUID_maxval == 0 || s->limit_CPUID_maxval == 1); assert(s->xTPR_message_disable == 0 || s->xTPR_message_disable == 1); assert(s->XD_bit_disable == 0 || s->XD_bit_disable == 1); assert(s->turbo_mode_disable == 0 || s->turbo_mode_disable == 1); msrVal = (msrVal & (~(1<< 0))) | (s->fast_string_enable << 0); msrVal = (msrVal & (~(1<< 3))) | (s->auto_TCC_enable << 3); msrVal = (msrVal & (~(1<< 13))) | (s->TM2_enable << 13); msrVal = (msrVal & (~(1<< 16))) | (s->enhanced_Intel_SpeedStep_Tech_enable << 16); msrVal = (msrVal & (~(1<< 22))) | (s->limit_CPUID_maxval << 22); msrVal = (msrVal & (~(1<< 23))) | (s->xTPR_message_disable << 23); msrVal = (msrVal & (~((uint64_t)1<< (uint64_t)34))) | ((uint64_t)s->XD_bit_disable << (uint64_t)34); msrVal = (msrVal & (~((uint64_t)1<< (uint64_t)38))) | ((uint64_t)s->turbo_mode_disable << (uint64_t)38); write_msr_by_coord(package, 0, 0, IA32_MISC_ENABLE, msrVal); }
void get_clock_mod(int socket, int core, struct clock_mod *s) { read_msr_by_coord(socket, core, 0, IA32_CLOCK_MODULATION, &(s->raw)); //s->raw = 64; // temp value s->duty_cycle = MASK_VAL(s->raw, 3, 1); // specific encoded values for target duty cycle s->duty_cycle_enable = MASK_VAL(s->raw, 4, 4); // On-Demand Clock Modulation Enable // 1 = enabled, 0 disabled }
int set_clock_mod(int socket, int core, struct clock_mod *s) { uint64_t msrVal; read_msr_by_coord(socket, core, 0, IA32_CLOCK_MODULATION, &msrVal); //msrVal = 64; // temp value // replaced asserts with these two conditionals if (!(s->duty_cycle > 0 && s->duty_cycle < 8)) { return -1; } if (!(s->duty_cycle_enable == 0 || s->duty_cycle_enable == 1)) { return -1; } msrVal = (msrVal & (~(3<<1))) | (s->duty_cycle << 1); msrVal = (msrVal & (~(1<<4))) | (s->duty_cycle_enable << 4); write_msr_by_coord(socket, core, 0, IA32_CLOCK_MODULATION, msrVal); return 0; }
int set_pkg_rapl_limit(const unsigned socket, struct rapl_limit *limit1, struct rapl_limit *limit2) { uint64_t pkg_limit = 0; static uint64_t *rapl_flags = NULL; uint64_t currentval = 0; int ret = 0; sockets_assert(&socket, __LINE__, __FILE__); if (rapl_flags == NULL) { if (rapl_storage(NULL, &rapl_flags)) { return -1; } } #ifdef LIBMSR_DEBUG fprintf(stderr, "%s %s::%d DEBUG: (set_pkg_rapl_limit) flags are at %p\n", getenv("HOSTNAME"), __FILE__, __LINE__, rapl_flags); #endif /* Make sure the pkg power limit register exists. */ if (*rapl_flags & PKG_POWER_LIMIT) { /* If there is only one limit, grab the other existing one. */ if (limit1 == NULL) { #ifdef LIBMSR_DEBUG fprintf(stderr, "%s %s::%d DEBUG: only one rapl limit, retrieving any existing power limits\n", getenv("HOSTNAME"), __FILE__, __LINE__); #endif ret = read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, ¤tval); /* We want to keep the lower limit so mask off all other bits. */ pkg_limit |= currentval & 0x00000000FFFFFFFF; } else if (limit2 == NULL) { #ifdef LIBMSR_DEBUG fprintf(stderr, "%s %s::%d DEBUG: only one rapl limit, retrieving any existing power limits\n", getenv("HOSTNAME"), __FILE__, __LINE__); #endif ret = read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, ¤tval); /* We want to keep the upper limit so mask off all other bits. */ pkg_limit |= currentval & 0xFFFFFFFF00000000; } if (calc_pkg_rapl_limit(socket, limit1, limit2)) { return -1; } /* Enable the rapl limit (15 && 47) and turn on clamping (16 && 48). */ if (limit1 != NULL) { pkg_limit |= limit1->bits | (1LL << 15) | (1LL << 16); } if (limit2 != NULL) { pkg_limit |= limit2->bits | (1LL << 47) | (1LL << 48); } if (limit1 != NULL || limit2 != NULL) { ret += write_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, pkg_limit); } } else { libmsr_error_handler("set_pkg_rapl_limit(): PKG domain RAPL limit not supported on this architecture", LIBMSR_ERROR_PLATFORM_NOT_SUPPORTED, getenv("HOSTNAME"), __FILE__, __LINE__); return -1; } #ifdef LIBMSR_DEBUG fprintf(stderr, "pkg set\n"); #endif return ret; }
void get_rapl_power_unit(struct rapl_units *ru) { static int init = 0; static uint64_t sockets = 0; static uint64_t **val = NULL; int i; sockets = num_sockets(); if (!init) { init = 1; val = (uint64_t **) libmsr_calloc(sockets, sizeof(uint64_t *)); allocate_batch(RAPL_UNIT, sockets); load_socket_batch(MSR_RAPL_POWER_UNIT, val, RAPL_UNIT); } read_batch(RAPL_UNIT); /* Initialize the units used for each socket. */ for (i = 0; i < sockets; i++) { // See figure 14-16 for bit fields. // 1 1 1 1 1 // 9 6 5 2 1 8 7 4 3 0 // // 1010 0001 0000 0000 0011 // // A 1 0 0 3 //ru[i].msr_rapl_power_unit = 0xA1003; ru[i].msr_rapl_power_unit = *val[i]; /* Default is 1010b or 976 microseconds. */ /* Storing (1/(2^TU))^-1 for maximum precision. */ ru[i].seconds = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 19, 16))); /* Default is 10000b or 15.3 microjoules. */ /* Storing (1/(2^ESU))^-1 for maximum precision. */ ru[i].joules = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 12, 8))); #ifdef LIBMSR_DEBUG fprintf(stderr, "DEBUG: joules unit is %f register has %lx\n", ru[i].joules, ru[i].msr_rapl_power_unit); #endif /* Default is 0011b or 1/8 Watts. */ ru[i].watts = ((1.0)/((double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 3, 0))))); #ifdef LIBMSR_DEBUG fprintf(stdout, "Pkg %d MSR_RAPL_POWER_UNIT\n", i); fprintf(stdout, "Raw: %f sec, %f J, %f watts\n", ru[i].seconds, ru[i].joules, ru[i].watts); fprintf(stdout, "Adjusted: %f sec, %f J, %f watts\n", 1/ru[i].seconds, 1/ru[i].joules, ru[i].watts); #endif } /* Check consistency between packages. */ uint64_t *tmp = (uint64_t *) libmsr_calloc(sockets, sizeof(uint64_t)); for (i = 0; i < sockets; i++) { read_msr_by_coord(i, 0, 0, MSR_RAPL_POWER_UNIT, tmp); double energy = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 12, 8))); double seconds = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 19, 16))); double power = ((1.0)/((double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 3, 0))))); if (energy != ru[i].joules || power != ru[i].watts || seconds != ru[i].seconds) { libmsr_error_handler("get_rapl_power_unit(): Inconsistent rapl power units across packages", LIBMSR_ERROR_RUNTIME, getenv("HOSTNAME"), __FILE__, __LINE__); } } }
void get_misc_enable(int package, struct misc_enable *s) { read_msr_by_coord(package, 0, 0, IA32_MISC_ENABLE, &(s->raw)); //s->raw = 164; s->fast_string_enable = MASK_VAL(s->raw, 0, 0); // When set, fast-strings feature (for REP MOVS and REP STORS) // is enabled (default), (cleared = disabled) s->auto_TCC_enable = MASK_VAL(s->raw, 3, 3); // 0 = disabled (default) // Note: clearing might be ignored in critical thermal // conditions. In this case, TM1, TM2, and adaptive // thermal throttling will still be active. // // 1 = enables the thermal control circuit (TCC) portion // of the Intel Thermal Monitor feature. Allows the // processor to automatically reduce power consumption in // response to TCC activation) s->performance_monitoring = MASK_VAL(s->raw, 7,7); // 1 = performance monitoring enabled // 0 = disabled s->branch_trace_storage_unavail = MASK_VAL(s->raw, 11, 11); // 1 = Processor doesn't support branch trace storage (BTS) // 0 = BTS is supported s->precise_event_based_sampling_unavail = MASK_VAL(s->raw, 12, 12); // 1 = PEBS is not supported // 0 = PEBS is supported s->TM2_enable = MASK_VAL(s->raw, 13, 13); // 1 = TM2 enabled // 0 = TM2 disabled s->enhanced_Intel_SpeedStep_Tech_enable = MASK_VAL(s->raw, 16, 16); // 1 = Enhanced Intel SpeedStep Technology enabled // 0 = disabled s->enable_monitor_fsm = MASK_VAL(s->raw, 18, 18); // 0 = MONITOR feature flag is not set (CPUID.01H:ECX[bit 3]=0) // This indicates that MONITOR/MWAIT are not supported. // Software attempts to execute MONITOR/MWAIT will cause #UD // when this bit is 0. // 1 (default) = MONITOR/MWAIT are supported. (CPUID... = 1) // // If the SSE3 feature flag ECX[0] is not set // (CPUID.01H:ECX[bit 0] = 0), the OS must not attempt to // alter this bit. BIOS must leave it in the default state. // Writing this bit when SSE3 feature flag is 0 may generate // a #GP exception s->limit_CPUID_maxval = MASK_VAL(s->raw, 22, 22); // Before setting this bit, BIOS must execute the CPUID.0H // and examine the maximum value returned in EAX[7:0]. // If the max is greater than 3, bit is supported. // Otherwise, this bit is not supported, and writing to this // bit when the max value is greater than 3 may generate // a #GP exception // // Setting this bit may cause unexpected behavior in software // that depends on the availability of CPUID leaves greater // than 3. // // 1 = CPUID.00H returns a max value in EAX[7:0] of 3. // BIOS should contain a setup question that allows users to // specify when the installed OS does not support CPUID // functions greater than 3. s->xTPR_message_disable = MASK_VAL(s->raw, 23, 23); // xTPR messages are optional messages that allow the // processor to inform the chipset of its priority. // 1 = xTPR messages are disabled // 0 = enabled s->XD_bit_disable = MASK_VAL(s->raw, 34, 34); // BIOS must not alter the contents of this bit location. If // XD is not supported, writing this bit to 1 when the XD Bit // extended flag is set 0 may generate a #GP exception // // 1 = Execute Disable Bit feature (XD bit) is disabled // and the XD bit extended feature flag will be clear // (CPUID.80000001H:EDX[20] = 0 // // 0 (default) = the EX bit feature (if available) allows // the OS to enable PAE paging and take advantage of data // only pages s->turbo_mode_disable = MASK_VAL(s->raw, 38, 38); // 1 (on processors that support Intel Turbo Boost Tech) = // turbo mode feature disabled and IDA_Enable feature flag // will be clear (CPUID.06H: EAX[1]=0) // // 0 (on proccessors that support IDA) = CPUID.06H: EAX[1] // reports the processor's support of turbo mode is enabled // // Note: the power on default value is used by BIOS to detect // hardware support of turbo mode. If power-on default is 1, // turbo mode is available in the processor. If 0, then turbo // mode is not available. }