1
0
Fork 0
mirror of https://github.com/anrieff/libcpuid synced 2024-11-10 22:59:13 +00:00

RDMSR: use double instead of uint64_t for AMD CPU multipliers

Multipliers can be a decimal number, like 7.5x
This commit is contained in:
Xorg 2017-04-30 21:08:15 +02:00
parent 84f95c8ad0
commit 5a02be091a

View file

@ -619,7 +619,7 @@ static int perfmsr_measure(struct msr_driver_t* handle, int msr)
return (int) ((y - x) / (b - a));
}
static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, uint64_t *multiplier)
static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, double *multiplier)
{
int i, err;
uint64_t CpuFid, CpuDid, CpuDidLSD;
@ -640,7 +640,7 @@ static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, uint64_
/* Constant values for common families */
const int magic_constant = (info->id->ext_family == 0x11) ? 0x8 : 0x10;
const int divisor = ((FUSION_C <= info->internal->code.amd) && (info->internal->code.amd <= FUSION_A)) ? 1 : 2;
const double divisor = ((FUSION_C <= info->internal->code.amd) && (info->internal->code.amd <= FUSION_A)) ? 1.0 : 2.0;
/* Check if P-state is valid */
if (pstate < MSR_PSTATE_0 || MSR_PSTATE_7 < pstate)
@ -659,7 +659,7 @@ static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, uint64_
while (i < num_dids && divisor_t[i].did != CpuDid)
i++;
if (i < num_dids)
*multiplier = (uint64_t) ((CpuFid + 0x10) / divisor_t[i].divisor);
*multiplier = (double) ((CpuFid + magic_constant) / divisor_t[i].divisor);
else
err++;
break;
@ -673,7 +673,7 @@ static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, uint64_
Note: This family contains only APUs */
err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &CpuDid);
err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &CpuDidLSD);
*multiplier = (uint64_t) (((info->cpu_clock + 5) / 100 + 0x10) / (CpuDid + CpuDidLSD * 0.25 + 1));
*multiplier = (double) (((info->cpu_clock + 5) / 100 + magic_constant) / (CpuDid + CpuDidLSD * 0.25 + 1));
break;
case 0x10:
/* BKDG 10h, page 429
@ -701,7 +701,7 @@ static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, uint64_
Note: This family contains only APUs */
err = cpu_rdmsr_range(info->handle, pstate, 8, 6, &CpuDid);
err += cpu_rdmsr_range(info->handle, pstate, 5, 0, &CpuFid);
*multiplier = (uint64_t) ((CpuFid + magic_constant) / (1ull << CpuDid)) / divisor;
*multiplier = (double) ((CpuFid + magic_constant) / (1ull << CpuDid)) / divisor;
break;
case 0x17:
/* PPR 17h, pages 30 and 138-139
@ -710,7 +710,7 @@ static int get_amd_multipliers(struct msr_info_t *info, uint32_t pstate, uint64_
CoreCOF is (Core::X86::Msr::PStateDef[CpuFid[7:0]] / Core::X86::Msr::PStateDef[CpuDfsId]) * 200 */
err = cpu_rdmsr_range(info->handle, pstate, 13, 8, &CpuDid);
err += cpu_rdmsr_range(info->handle, pstate, 7, 0, &CpuFid);
*multiplier = (uint64_t) (CpuFid / CpuDid) * 2;
*multiplier = (double) (CpuFid / CpuDid) * 2;
break;
default:
err = 1;
@ -743,6 +743,7 @@ static uint32_t get_amd_last_pstate_addr(struct msr_info_t *info)
static double get_info_min_multiplier(struct msr_info_t *info)
{
int err;
double mult;
uint32_t addr;
uint64_t reg;
@ -765,8 +766,8 @@ static double get_info_min_multiplier(struct msr_info_t *info)
/* N.B.: Find the last P-state
get_amd_last_pstate_addr() returns the last P-state, MSR_PSTATE_0 <= addr <= MSR_PSTATE_7 */
addr = get_amd_last_pstate_addr(info);
err = get_amd_multipliers(info, addr, &reg);
if (!err) return (double) reg;
err = get_amd_multipliers(info, addr, &mult);
if (!err) return mult;
}
return (double) CPU_INVALID_VALUE / 100;
@ -775,6 +776,7 @@ static double get_info_min_multiplier(struct msr_info_t *info)
static double get_info_cur_multiplier(struct msr_info_t *info)
{
int err;
double mult;
uint64_t reg;
if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel == PENTIUM) {
@ -793,8 +795,8 @@ static double get_info_cur_multiplier(struct msr_info_t *info)
/* Refer links above
MSRC001_0063[2:0] is CurPstate */
err = cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, &reg);
err += get_amd_multipliers(info, MSR_PSTATE_0 + (uint32_t) reg, &reg);
if (!err) return (double) reg;
err += get_amd_multipliers(info, MSR_PSTATE_0 + (uint32_t) reg, &mult);
if (!err) return mult;
}
return (double) CPU_INVALID_VALUE / 100;
@ -803,6 +805,7 @@ static double get_info_cur_multiplier(struct msr_info_t *info)
static double get_info_max_multiplier(struct msr_info_t *info)
{
int err;
double mult;
uint64_t reg;
if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel == PENTIUM) {
@ -832,8 +835,8 @@ static double get_info_max_multiplier(struct msr_info_t *info)
/* Refer links above
MSRC001_0064 is Pb0
Pb0 is the highest-performance boosted P-state */
err = get_amd_multipliers(info, MSR_PSTATE_0, &reg);
if (!err) return (double) reg;
err = get_amd_multipliers(info, MSR_PSTATE_0, &mult);
if (!err) return mult;
}
return (double) CPU_INVALID_VALUE / 100;
@ -902,6 +905,7 @@ static double get_info_voltage(struct msr_info_t *info)
static double get_info_bus_clock(struct msr_info_t *info)
{
int err;
double mult;
uint32_t addr;
uint64_t reg;
@ -924,8 +928,8 @@ static double get_info_bus_clock(struct msr_info_t *info)
PstateMaxVal is the the lowest-performance non-boosted P-state */
addr = get_amd_last_pstate_addr(info);
err = cpu_rdmsr_range(info->handle, MSR_PSTATE_L, 6, 4, &reg);
err += get_amd_multipliers(info, addr - reg, &reg);
if (!err) return (double) info->cpu_clock / reg;
err += get_amd_multipliers(info, addr - reg, &mult);
if (!err) return (double) info->cpu_clock / mult;
}
return (double) CPU_INVALID_VALUE / 100;