/** * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz * values into per cent values. In TMTA microcode, the following is valid: * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
*/ staticunsignedint longrun_low_freq, longrun_high_freq;
/** * longrun_get_policy - get the current LongRun policy * @policy: struct cpufreq_policy where current policy is written into * * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS * and MSR_TMTA_LONGRUN_CTRL
*/ staticvoid longrun_get_policy(struct cpufreq_policy *policy)
{
u32 msr_lo, msr_hi;
/** * longrun_set_policy - sets a new CPUFreq policy * @policy: new policy * * Sets a new CPUFreq policy on LongRun-capable processors. This function * has to be called with cpufreq_driver locked.
*/ staticint longrun_set_policy(struct cpufreq_policy *policy)
{
u32 msr_lo, msr_hi;
u32 pctg_lo, pctg_hi;
/** * longrun_verify_poliy - verifies a new CPUFreq policy * @policy: the policy to verify * * Validates a new CPUFreq policy. This function has to be called with * cpufreq_driver locked.
*/ staticint longrun_verify_policy(struct cpufreq_policy_data *policy)
{ if (!policy) return -EINVAL;
cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
pr_debug("cpuid eax is %u\n", eax);
return eax * 1000;
}
/** * longrun_determine_freqs - determines the lowest and highest possible core frequency * @low_freq: an int to put the lowest frequency into * @high_freq: an int to put the highest frequency into * * Determines the lowest and highest possible core frequencies on this CPU. * This is necessary to calculate the performance percentage according to * TMTA rules: * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
*/ staticint longrun_determine_freqs(unsignedint *low_freq, unsignedint *high_freq)
{
u32 msr_lo, msr_hi;
u32 save_lo, save_hi;
u32 eax, ebx, ecx, edx;
u32 try_hi; struct cpuinfo_x86 *c = &cpu_data(0);
if (!low_freq || !high_freq) return -EINVAL;
if (cpu_has(c, X86_FEATURE_LRTI)) { /* if the LongRun Table Interface is present, the * detection is a bit easier: * For minimum frequency, read out the maximum * level (msr_hi), write that into "currently * selected level", and read out the frequency. * For maximum frequency, read out level zero.
*/ /* minimum */
rdmsr(MSR_TMTA_LRTI_READOUT, msr_lo, msr_hi);
wrmsr(MSR_TMTA_LRTI_READOUT, msr_hi, msr_hi);
rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi);
*low_freq = msr_lo * 1000; /* to kHz */
/* maximum */
wrmsr(MSR_TMTA_LRTI_READOUT, 0, msr_hi);
rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi);
*high_freq = msr_lo * 1000; /* to kHz */
if (*low_freq > *high_freq)
*low_freq = *high_freq; return 0;
}
/* set the upper border to the value determined during TSC init */
*high_freq = (cpu_khz / 1000);
*high_freq = *high_freq * 1000;
pr_debug("high frequency is %u kHz\n", *high_freq);
/* get current borders */
rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
save_lo = msr_lo & 0x0000007F;
save_hi = msr_hi & 0x0000007F;
/* if current perf_pctg is larger than 90%, we need to decrease the * upper limit to make the calculation more accurate.
*/
cpuid(0x80860007, &eax, &ebx, &ecx, &edx); /* try decreasing in 10% steps, some processors react only
* on some barrier values */ for (try_hi = 80; try_hi > 0 && ecx > 90; try_hi -= 10) { /* set to 0 to try_hi perf_pctg */
msr_lo &= 0xFFFFFF80;
msr_hi &= 0xFFFFFF80;
msr_hi |= try_hi;
wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
/* read out current core MHz and current perf_pctg */
cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
/* restore values */
wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);
}
pr_debug("percentage is %u %%, freq is %u MHz\n", ecx, eax);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.