bool cpuid_pkg_therm_Stat_AND_Interrupt() { uint32_t eax, ebx, ecx, edx; int leaf = 6; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(eax, 6, 6) == 1) { return true; } else { return false; } }
bool cpuid_MPERF_and_APERF() { uint32_t eax, ebx, ecx, edx; int leaf = 6; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(ecx, 0, 0) == 1) { return true; } else { return false; } }
bool cpuid_therm_stat_readout() { uint32_t eax, ebx, ecx, edx; int leaf = 6; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(eax, 0, 0) == 1) { return true; } else { return false; } }
bool cpuid_therm_interrupt_powerlimit() { uint32_t eax, ebx, ecx, edx; int leaf = 6; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(eax, 4, 4) == 1) { return true; } else { return false; } }
bool cpuid_clock_mod_extended() { uint32_t eax, ebx, ecx, edx; int leaf = 6; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(eax, 5,5) == 1) { return true; } else { return false; } }
bool cpuid_therm_stat_therm_thresh() { uint32_t eax, ebx, ecx, edx; int leaf = 1; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(ecx, 8, 8) == 1) { return true; } else { return false; } }
bool cpuid_misc_enable_xTPRmessageDisable() { uint32_t eax, ebx, ecx, edx; int leaf = 1; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(ecx, 14, 14) == 1) { return true; } else { return false; } }
bool cpuid_perf_global_ctrl_EN_FIXED_CTRnum() { uint32_t eax, ebx, ecx, edx; int leaf = 10; // 0A cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(eax, 7,0) > 1) { return true; } else { return false; } }
bool cpuid_misc_enable_turboBoost() { uint32_t eax, ebx, ecx, edx; int leaf = 6; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(eax, 1, 1) == 1) { return true; } else { return false; } }
bool cpuid_timeStampCounter_avail() { uint32_t eax, ebx, ecx, edx; int leaf = 1; cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(edx,4,4) == 1) { return true; } else { return false; } }
bool cpuid_misc_enable_XDbitDisable() { uint32_t eax, ebx, ecx, edx; int leaf = 2147483649; // 80000001H cpuid(leaf, &eax, &ebx, &ecx, &edx); if(MASK_VAL(edx, 20, 20) == 1) { return true; } else { return false; } }
void clock_init(){ reg_rst_clk0 = 0xff000000 | (CLK_USB_ENABLE ? FLD_CLK_USB_EN: 0); #if(CLOCK_SYS_TYPE == CLOCK_TYPE_PLL) reg_clk_sel = MASK_VAL(FLD_CLK_SEL_DIV, (CLOCK_PLL_CLOCK / CLOCK_SYS_CLOCK_1S), FLD_CLK_SEL_SRC, CLOCK_SEL_HS_DIV); #elif(CLOCK_SYS_TYPE == CLOCK_TYPE_PAD) //STATIC_ASSERT(CLK_FHS_MZ == 32); #if(CLOCK_SYS_CLOCK_HZ == 12000000) reg_clk_sel = 0x40; #else #error clock not set properly #endif #elif(CLOCK_SYS_TYPE == CLOCK_TYPE_OSC) //STATIC_ASSERT(CLK_FHS_MZ == 32); #if(CLOCK_SYS_CLOCK_HZ == 32000000) reg_fhs_sel = 0; reg_clk_sel = 0; // must be zero #elif(CLOCK_SYS_CLOCK_HZ == 16000000) reg_fhs_sel = FHS_SEL_32M_OSC; reg_clk_sel = MASK_VAL(FLD_CLK_SEL_DIV, 2, FLD_CLK_SEL_SRC, CLOCK_SEL_HS_DIV); #elif(CLOCK_SYS_CLOCK_HZ == 8000000) reg_fhs_sel = FHS_SEL_32M_OSC; reg_clk_sel = MASK_VAL(FLD_CLK_SEL_DIV, 4, FLD_CLK_SEL_SRC, CLOCK_SEL_HS_DIV); #else #error clock not set properly #endif #else #error clock not set properly #endif //reg_clk_en = 0xff | CLK_EN_TYPE; reg_tmr_ctrl = MASK_VAL(FLD_TMR0_EN, 1 , FLD_TMR_WD_CAPT, (MODULE_WATCHDOG_ENABLE ? (WATCHDOG_INIT_TIMEOUT * CLOCK_SYS_CLOCK_1MS >> WATCHDOG_TIMEOUT_COEFF):0) , FLD_TMR_WD_EN, (MODULE_WATCHDOG_ENABLE?1:0)); }
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. }
#include <console/console.h> #include <reg_script.h> #include <baytrail/iosf.h> #define MAKE_MASK_INCLUSIVE(msb) \ ((1ULL << (1 + (msb))) - 1) #define MAKE_MASK(msb) \ ((1ULL << (msb)) - 1) #define MASK_VAL(msb, lsb, val) \ ~(MAKE_MASK_INCLUSIVE(msb) & ~MAKE_MASK(lsb)), (val) << (lsb) #define E(arg1, arg2, args) \ REG_IOSF_RMW(IOSF_PORT_##arg1, arg2, args) static const struct reg_script perf_power_settings[] = { E(AUNIT, 0x18, MASK_VAL(22, 22, 0x1)), // ACKGATE.AMESSAGE_MSGIF E(AUNIT, 0x18, MASK_VAL(21, 21, 0x1)), // ACKGATE.AREQDOWN_SCL0_ARB E(AUNIT, 0x18, MASK_VAL(20, 20, 0x1)), // ACKGATE.AREQUP_MIRROR E(AUNIT, 0x18, MASK_VAL(19, 19, 0x1)), // ACKGATE.AREQTAHACK E(AUNIT, 0x18, MASK_VAL(18, 18, 0x1)), // ACKGATE.AREQDOWN_TAREQQ E(AUNIT, 0x18, MASK_VAL(17, 17, 0x1)), // ACKGATE.AREQDOWN_CREDIT E(AUNIT, 0x18, MASK_VAL(16, 16, 0x1)), // ACKGATE.ASCLUP_FAIR_ARBITER E(AUNIT, 0x18, MASK_VAL(15, 15, 0x1)), // ACKGATE.AIOSFDOWN_DATA E(AUNIT, 0x18, MASK_VAL(14, 14, 0x1)), // ACKGATE.ASCLUP_IOSF_ADAPTER E(AUNIT, 0x18, MASK_VAL(12, 12, 0x1)), // ACKGATE.ASCLUP_CMD_QUEUE E(AUNIT, 0x18, MASK_VAL(11, 11, 0x1)), // ACKGATE.ASCLUP_DATA_QUEUE E(AUNIT, 0x18, MASK_VAL(10, 10, 0x1)), // ACKGATE.AREQUP_CMD_QUEUE E(AUNIT, 0x18, MASK_VAL(9, 9, 0x1)), // ACKGATE.AREQUP_DATA_QUEUE E(AUNIT, 0x18, MASK_VAL(8, 8, 0x1)), // ACKGATE.AREQDOWN_RSP_QUEUE E(AUNIT, 0x18, MASK_VAL(7, 7, 0x1)), // ACKGATE.AREQDOWN_DATA_QUEUE E(AUNIT, 0x18, MASK_VAL(6, 6, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DRVR
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_power_limit( int package, int domain, struct power_limit_s *limit, struct power_unit_s *units ){ uint64_t val; get_raw_power_limit( package, domain, &val ); if(domain == PKG_DOMAIN){ limit->time_window_2 = MASK_VAL(val, 53, 49); limit->power_limit_2 = MASK_VAL(val, 46, 32); limit->clamp_2 = MASK_VAL(val, 48, 48); limit->enable_2 = MASK_VAL(val, 47, 47); limit->time_multiplier_2= MASK_VAL(val, 55, 54); limit->lock = MASK_VAL(val, 63, 63); }else{ limit->lock = MASK_VAL(val, 31, 31); } limit->power_limit_1 = MASK_VAL(val, 14, 0); limit->enable_1 = MASK_VAL(val, 15, 15); limit->clamp_1 = MASK_VAL(val, 16, 16); limit->time_window_1 = MASK_VAL(val, 21, 17); limit->time_multiplier_1= MASK_VAL(val, 23, 22); // There are several more clever ways of doing this. // I don't care. if(domain == PKG_DOMAIN){ switch(limit->time_multiplier_2){ case 3: limit->time_multiplier_float_2 = 1.3; break; case 2: limit->time_multiplier_float_2 = 1.2; break; case 1: limit->time_multiplier_float_2 = 1.1; break; case 0: limit->time_multiplier_float_2 = 1.0; break; default: // Should never, ever get here. fprintf(stderr, "%s::%d BADNESS! limit->time_multiplier_2 = %lx!\n", __FILE__, __LINE__, limit->time_multiplier_2 ); } limit->time_window_2_sec = UNIT_SCALE(1 << limit->time_window_2, units->time) * limit->time_multiplier_float_2; limit->power_limit_2_watts = UNIT_SCALE(limit->power_limit_2, units->power); } switch(limit->time_multiplier_1){ case 3: limit->time_multiplier_float_1 = 1.3; break; case 2: limit->time_multiplier_float_1 = 1.2; break; case 1: limit->time_multiplier_float_1 = 1.1; break; case 0: limit->time_multiplier_float_1 = 1.0; break; default: // Should never, ever get here. fprintf(stderr, "%s::%d BADNESS! limit->time_multiplier_1 = %lx!\n", __FILE__, __LINE__, limit->time_multiplier_1 ); } limit->time_window_1_sec = UNIT_SCALE(1 << limit->time_window_1, units->time) * limit->time_multiplier_float_1; /* fprintf( stderr, "%s::%d limit->time_window_1= 0x%lx, units->time=0x%x, UNIT_SCALE(limit->time_window_1, units->time)=%lf, limit->time_window_1_sec=%lf, limit->time_multiplier_1=%lf\n", __FILE__, __LINE__, limit->time_window_1, units->time, UNIT_SCALE(limit->time_window_1, units->time), limit->time_window_1_sec, limit->time_multiplier_1); */ limit->power_limit_1_watts = UNIT_SCALE(limit->power_limit_1, units->power); if( msr_debug && (domain == PKG_DOMAIN) ){ fprintf( stderr, "%s::%d power limit time window 2 = 0x%lx\n", __FILE__, __LINE__, limit->time_window_2 ); fprintf( stderr, "%s::%d power limit power limit 2 = 0x%lx\n", __FILE__, __LINE__, limit->power_limit_2 ); fprintf( stderr, "%s::%d power limit clamp 2 = 0x%lx\n", __FILE__, __LINE__, limit->clamp_2 ); fprintf( stderr, "%s::%d power limit enable 2 = 0x%lx\n", __FILE__, __LINE__, limit->enable_2 ); fprintf( stderr, "%s::%d time multiplier 2 = 0x%lx\n", __FILE__, __LINE__, limit->time_multiplier_2 ); fprintf( stderr, "%s::%d time_window_2_sec = %15.10lf\n", __FILE__, __LINE__, limit->time_window_2_sec ); fprintf( stderr, "%s::%d power_limit_2_watts = %15.10lf\n", __FILE__, __LINE__, limit->power_limit_2_watts ); fprintf( stderr, "%s::%d time_multiplier_float_2 = %15.10lf\n", __FILE__, __LINE__, limit->time_multiplier_float_2 ); } if( msr_debug ){ fprintf( stderr, "%s::%d power limit lock = 0x%lx\n", __FILE__, __LINE__, limit->lock ); fprintf( stderr, "%s::%d power limit time window 1 = 0x%lx\n", __FILE__, __LINE__, limit->time_window_1 ); fprintf( stderr, "%s::%d power limit power limit 1 = 0x%lx\n", __FILE__, __LINE__, limit->power_limit_1 ); fprintf( stderr, "%s::%d power limit clamp 1 = 0x%lx\n", __FILE__, __LINE__, limit->clamp_1 ); fprintf( stderr, "%s::%d power limit enable 1 = 0x%lx\n", __FILE__, __LINE__, limit->enable_1 ); fprintf( stderr, "%s::%d time multiplier 1 = 0x%lx\n", __FILE__, __LINE__, limit->time_multiplier_1 ); fprintf( stderr, "%s::%d time_window_1_sec = %15.10lf\n", __FILE__, __LINE__, limit->time_window_1_sec ); fprintf( stderr, "%s::%d power_limit_1_watts = %15.10lf\n", __FILE__, __LINE__, limit->power_limit_1_watts ); fprintf( stderr, "%s::%d time_multiplier_float_1 = %15.10lf\n", __FILE__, __LINE__, limit->time_multiplier_float_1 ); } }
void get_fixed_ctr_ctrl(struct ctr_data *ctr0, struct ctr_data *ctr1, struct ctr_data *ctr2){ uint64_t perf_global_ctrl[NUM_THREADS]; uint64_t fixed_ctr_ctrl[NUM_THREADS]; int i; read_all_threads(IA32_PERF_GLOBAL_CTRL, perf_global_ctrl); read_all_threads(IA32_FIXED_CTR_CTRL, fixed_ctr_ctrl); for(i=0; i<NUM_THREADS; i++){ if(ctr0){ ctr0->enable[i] = MASK_VAL(perf_global_ctrl[i], 32, 32); ctr0->ring_level[i] = MASK_VAL(fixed_ctr_ctrl[i], 1,0); ctr0->anyThread[i] = MASK_VAL(fixed_ctr_ctrl[i], 2,2); ctr0->pmi[i] = MASK_VAL(fixed_ctr_ctrl[i], 3,3); } if(ctr1){ ctr1->enable[i] = MASK_VAL(perf_global_ctrl[i], 33, 33); ctr1->ring_level[i] = MASK_VAL(fixed_ctr_ctrl[i], 5,4); ctr1->anyThread[i] = MASK_VAL(fixed_ctr_ctrl[i], 6,6); ctr1->pmi[i] = MASK_VAL(fixed_ctr_ctrl[i], 7,7); } if(ctr2){ ctr2->enable[i] = MASK_VAL(perf_global_ctrl[i], 34, 34); ctr2->ring_level[i] = MASK_VAL(fixed_ctr_ctrl[i], 9,8); ctr2->anyThread[i] = MASK_VAL(fixed_ctr_ctrl[i], 10, 10); ctr2->pmi[i] = MASK_VAL(fixed_ctr_ctrl[i], 11,11); } } }