123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- #if defined(__i386__) || defined(__x86_64__)
- #include <unistd.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <pci/pci.h>
- #include "helpers/helpers.h"
- #define MSR_AMD_PSTATE_STATUS 0xc0010063
- #define MSR_AMD_PSTATE 0xc0010064
- #define MSR_AMD_PSTATE_LIMIT 0xc0010061
- union msr_pstate {
- struct {
- unsigned fid:6;
- unsigned did:3;
- unsigned vid:7;
- unsigned res1:6;
- unsigned nbdid:1;
- unsigned res2:2;
- unsigned nbvid:7;
- unsigned iddval:8;
- unsigned idddiv:2;
- unsigned res3:21;
- unsigned en:1;
- } bits;
- unsigned long long val;
- };
- static int get_did(int family, union msr_pstate pstate)
- {
- int t;
- if (family == 0x12)
- t = pstate.val & 0xf;
- else
- t = pstate.bits.did;
- return t;
- }
- static int get_cof(int family, union msr_pstate pstate)
- {
- int t;
- int fid, did;
- did = get_did(family, pstate);
- t = 0x10;
- fid = pstate.bits.fid;
- if (family == 0x11)
- t = 0x8;
- return (100 * (fid + t)) >> did;
- }
- /* Needs:
- * cpu -> the cpu that gets evaluated
- * cpu_family -> The cpu's family (0x10, 0x12,...)
- * boots_states -> how much boost states the machines support
- *
- * Fills up:
- * pstates -> a pointer to an array of size MAX_HW_PSTATES
- * must be initialized with zeros.
- * All available HW pstates (including boost states)
- * no -> amount of pstates above array got filled up with
- *
- * returns zero on success, -1 on failure
- */
- int decode_pstates(unsigned int cpu, unsigned int cpu_family,
- int boost_states, unsigned long *pstates, int *no)
- {
- int i, psmax, pscur;
- union msr_pstate pstate;
- unsigned long long val;
- /* Only read out frequencies from HW when CPU might be boostable
- to keep the code as short and clean as possible.
- Otherwise frequencies are exported via ACPI tables.
- */
- if (cpu_family < 0x10 || cpu_family == 0x14)
- return -1;
- if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val))
- return -1;
- psmax = (val >> 4) & 0x7;
- if (read_msr(cpu, MSR_AMD_PSTATE_STATUS, &val))
- return -1;
- pscur = val & 0x7;
- pscur += boost_states;
- psmax += boost_states;
- for (i = 0; i <= psmax; i++) {
- if (i >= MAX_HW_PSTATES) {
- fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n",
- psmax, MAX_HW_PSTATES);
- return -1;
- }
- if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val))
- return -1;
- pstates[i] = get_cof(cpu_family, pstate);
- }
- *no = i;
- return 0;
- }
- int amd_pci_get_num_boost_states(int *active, int *states)
- {
- struct pci_access *pci_acc;
- struct pci_dev *device;
- uint8_t val = 0;
- *active = *states = 0;
- device = pci_slot_func_init(&pci_acc, 0x18, 4);
- if (device == NULL)
- return -ENODEV;
- val = pci_read_byte(device, 0x15c);
- if (val & 3)
- *active = 1;
- else
- *active = 0;
- *states = (val >> 2) & 7;
- pci_cleanup(pci_acc);
- return 0;
- }
- #endif /* defined(__i386__) || defined(__x86_64__) */
|