mirror of
https://github.com/anrieff/libcpuid
synced 2024-11-10 22:59:13 +00:00
RDMSR: fix cpu_msrinfo() function with AMD CPUs
This commit is contained in:
parent
9b038c94c4
commit
d5c892e002
1 changed files with 42 additions and 44 deletions
|
@ -612,24 +612,16 @@ static int get_amd_multipliers(struct msr_driver_t* handle, struct cpu_id_t *id,
|
||||||
struct internal_id_info_t *internal,
|
struct internal_id_info_t *internal,
|
||||||
uint32_t pstate, uint64_t *multiplier)
|
uint32_t pstate, uint64_t *multiplier)
|
||||||
{
|
{
|
||||||
int err;
|
int i, err;
|
||||||
|
int divisor = 1;
|
||||||
|
int magic_constant = 0x10;
|
||||||
static int clock = 0;
|
static int clock = 0;
|
||||||
uint64_t CpuFid, CpuDid, CpuDidLSD;
|
uint64_t CpuFid, CpuDid, CpuDidLSD;
|
||||||
double divisor;
|
|
||||||
|
|
||||||
if (pstate < MSR_PSTATE_0 || MSR_PSTATE_7 < pstate)
|
if (pstate < MSR_PSTATE_0 || MSR_PSTATE_7 < pstate)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
switch (id->ext_family) {
|
switch (id->ext_family) {
|
||||||
case 0x11:
|
|
||||||
/* BKDG 11h, page 236
|
|
||||||
MSRC001_00[6B:64][8:6] is CpuDid
|
|
||||||
MSRC001_00[6B:64][5:0] is CpuFid
|
|
||||||
CPU COF is ((100 MHz * (CpuFid + 08h)) / (2^CpuDid)) */
|
|
||||||
err = cpu_rdmsr_range(handle, pstate, 8, 6, &CpuDid);
|
|
||||||
err += cpu_rdmsr_range(handle, pstate, 5, 0, &CpuFid);
|
|
||||||
*multiplier = (uint64_t) ((CpuFid + 0x8) / (1ull << CpuDid));
|
|
||||||
break;
|
|
||||||
case 0x12:
|
case 0x12:
|
||||||
/* BKDG 12h, page 469
|
/* BKDG 12h, page 469
|
||||||
MSRC001_00[6B:64][8:4] is CpuFid
|
MSRC001_00[6B:64][8:4] is CpuFid
|
||||||
|
@ -637,29 +629,23 @@ static int get_amd_multipliers(struct msr_driver_t* handle, struct cpu_id_t *id,
|
||||||
CPU COF is (100MHz * (CpuFid + 10h) / (divisor specified by CpuDid)) */
|
CPU COF is (100MHz * (CpuFid + 10h) / (divisor specified by CpuDid)) */
|
||||||
err = cpu_rdmsr_range(handle, pstate, 8, 4, &CpuFid);
|
err = cpu_rdmsr_range(handle, pstate, 8, 4, &CpuFid);
|
||||||
err += cpu_rdmsr_range(handle, pstate, 3, 0, &CpuDid);
|
err += cpu_rdmsr_range(handle, pstate, 3, 0, &CpuDid);
|
||||||
if (CpuDid == 0x0)
|
const struct { uint64_t did; double divisor; } divisor_t[] = {
|
||||||
divisor = 1;
|
{ 0x0, 1 },
|
||||||
else if (CpuDid == 0x1)
|
{ 0x1, 1.5 },
|
||||||
divisor = 1.5;
|
{ 0x2, 2 },
|
||||||
else if (CpuDid == 0x2)
|
{ 0x3, 3 },
|
||||||
divisor = 2;
|
{ 0x4, 4 },
|
||||||
else if (CpuDid == 0x3)
|
{ 0x5, 6 },
|
||||||
divisor = 3;
|
{ 0x6, 8 },
|
||||||
else if (CpuDid == 0x4)
|
{ 0x7, 12 },
|
||||||
divisor = 4;
|
{ 0x8, 16 },
|
||||||
else if (CpuDid == 0x5)
|
{ CpuDid, 0 },
|
||||||
divisor = 6;
|
};
|
||||||
else if (CpuDid == 0x6)
|
i = 0;
|
||||||
divisor = 8;
|
while(divisor_t[i].did != CpuDid)
|
||||||
else if (CpuDid == 0x7)
|
i++;
|
||||||
divisor = 12;
|
if (divisor_t[i].divisor > 0)
|
||||||
else if (CpuDid == 0x8)
|
*multiplier = (uint64_t) ((CpuFid + 0x10) / divisor_t[i].divisor);
|
||||||
divisor = 16;
|
|
||||||
else
|
|
||||||
divisor = 0;
|
|
||||||
|
|
||||||
if (divisor > 0)
|
|
||||||
*multiplier = (uint64_t) ((CpuFid + 0x10) / divisor);
|
|
||||||
else
|
else
|
||||||
err++;
|
err++;
|
||||||
break;
|
break;
|
||||||
|
@ -676,11 +662,19 @@ static int get_amd_multipliers(struct msr_driver_t* handle, struct cpu_id_t *id,
|
||||||
clock = cpu_clock_measure(100, 1) + 5; // Fake round
|
clock = cpu_clock_measure(100, 1) + 5; // Fake round
|
||||||
*multiplier = (uint64_t) ((clock / 100 + 0x10) / (CpuDid + CpuDidLSD * 0.25 + 1));
|
*multiplier = (uint64_t) ((clock / 100 + 0x10) / (CpuDid + CpuDidLSD * 0.25 + 1));
|
||||||
break;
|
break;
|
||||||
|
case 0x11:
|
||||||
|
/* BKDG 11h, page 236
|
||||||
|
MSRC001_00[6B:64][8:6] is CpuDid
|
||||||
|
MSRC001_00[6B:64][5:0] is CpuFid
|
||||||
|
CPU COF is ((100 MHz * (CpuFid + 08h)) / (2^CpuDid)) */
|
||||||
|
magic_constant = 0x8;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
/* BKDG 10h, page 429
|
/* BKDG 10h, page 429
|
||||||
MSRC001_00[6B:64][8:6] is CpuDid
|
MSRC001_00[6B:64][8:6] is CpuDid
|
||||||
MSRC001_00[6B:64][5:0] is CpuFid
|
MSRC001_00[6B:64][5:0] is CpuFid
|
||||||
CPU COF is (100 MHz * (CpuFid + 10h) / (2^CpuDid)) */
|
CPU COF is (100 MHz * (CpuFid + 10h) / (2^CpuDid))
|
||||||
|
N.B.: The (stock) bus speed is 200MHz on AMD 10h & 11h families, we need to divid by 2 */
|
||||||
|
divisor = 2;
|
||||||
case 0x15:
|
case 0x15:
|
||||||
/* BKDG 15h, page 570/580/635/692 (00h-0Fh/10h-1Fh/30h-3Fh/60h-6Fh)
|
/* BKDG 15h, page 570/580/635/692 (00h-0Fh/10h-1Fh/30h-3Fh/60h-6Fh)
|
||||||
MSRC001_00[6B:64][8:6] is CpuDid
|
MSRC001_00[6B:64][8:6] is CpuDid
|
||||||
|
@ -693,7 +687,7 @@ static int get_amd_multipliers(struct msr_driver_t* handle, struct cpu_id_t *id,
|
||||||
CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) */
|
CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) */
|
||||||
err = cpu_rdmsr_range(handle, pstate, 8, 6, &CpuDid);
|
err = cpu_rdmsr_range(handle, pstate, 8, 6, &CpuDid);
|
||||||
err += cpu_rdmsr_range(handle, pstate, 5, 0, &CpuFid);
|
err += cpu_rdmsr_range(handle, pstate, 5, 0, &CpuFid);
|
||||||
*multiplier = (uint64_t) ((CpuFid + 0x10) / (1ull << CpuDid));
|
*multiplier = (uint64_t) ((CpuFid + magic_constant) / (1ull << CpuDid)) / divisor;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
err = 1;
|
err = 1;
|
||||||
|
@ -707,6 +701,7 @@ static double get_info_min_multiplier(struct msr_driver_t* handle, struct cpu_id
|
||||||
struct internal_id_info_t *internal)
|
struct internal_id_info_t *internal)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
uint32_t addr = MSR_PSTATE_7 + 1;
|
||||||
uint64_t reg;
|
uint64_t reg;
|
||||||
|
|
||||||
if(id->vendor == VENDOR_INTEL) {
|
if(id->vendor == VENDOR_INTEL) {
|
||||||
|
@ -725,11 +720,14 @@ static double get_info_min_multiplier(struct msr_driver_t* handle, struct cpu_id
|
||||||
if (!err) return (double) reg;
|
if (!err) return (double) reg;
|
||||||
}
|
}
|
||||||
else if(id->vendor == VENDOR_AMD) {
|
else if(id->vendor == VENDOR_AMD) {
|
||||||
/* Refer links above
|
/* N.B.: Find the last P-state
|
||||||
MSRC001_0061[6:4] is PstateMaxVal
|
MSRC001_00[6B:64][8:0] is { CpuDid, CpuFid }
|
||||||
PstateMaxVal is the lowest-performance non-boosted P-state */
|
If all bits are 0 in a given P-state, we can consider the P-state is unused */
|
||||||
err = cpu_rdmsr_range(handle, MSR_PSTATE_L, 6, 4, ®);
|
do {
|
||||||
err += get_amd_multipliers(handle, id, internal, MSR_PSTATE_0 + (uint32_t) reg, ®);
|
addr--;
|
||||||
|
cpu_rdmsr_range(handle, addr, 8, 0, ®);
|
||||||
|
} while((reg == 0x0) && (addr > MSR_PSTATE_0));
|
||||||
|
err = get_amd_multipliers(handle, id, internal, addr, ®);
|
||||||
if (!err) return (double) reg;
|
if (!err) return (double) reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,9 +883,9 @@ static double get_info_bus_clock(struct msr_driver_t* handle, struct cpu_id_t *i
|
||||||
}
|
}
|
||||||
else if(id->vendor == VENDOR_AMD) {
|
else if(id->vendor == VENDOR_AMD) {
|
||||||
/* Refer links above
|
/* Refer links above
|
||||||
MSRC001_0061[2:0] is CurPstateLimit
|
MSRC001_0061[6:4] is PstateMaxVal
|
||||||
CurPstateLimit is the highest-performance non-boosted P-state */
|
PstateMaxVal is the the lowest-performance non-boosted P-state */
|
||||||
err = cpu_rdmsr_range(handle, MSR_PSTATE_L, 2, 0, ®);
|
err = cpu_rdmsr_range(handle, MSR_PSTATE_L, 6, 4, ®);
|
||||||
err += get_amd_multipliers(handle, id, internal, MSR_PSTATE_0 + (uint32_t) reg, ®);
|
err += get_amd_multipliers(handle, id, internal, MSR_PSTATE_0 + (uint32_t) reg, ®);
|
||||||
if (!err) return (double) clock / reg;
|
if (!err) return (double) clock / reg;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue