␉␊ |
␉if (acpi_cpu_count > 0) ␊ |
␉{␉␊ |
␉␉bool cpu_dynamic_fsb = false, cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));␊ |
␉␉␊ |
␉␉struct p_state initial, maximum, minimum, p_states[32];␊ |
␉␉uint8_t p_states_count;␉␉␊ |
␉␉uint8_t p_states_count = 0;␉␉␊ |
␉␉␊ |
␉␉// Retrieving P-States, ported from code by superhai (c)␊ |
␉␉switch (Platform.CPU.Family) {␊ |
|
␉␉␉␉␉case 0x0F: // Intel Core (65nm)␊ |
␉␉␉␉␉case 0x17: // Intel Core (45nm)␊ |
␉␉␉␉␉case 0x1C: // Intel Atom (45nm)␊ |
␉␉␉␉␉{␊ |
␉␉␉␉␉␉bool cpu_dynamic_fsb = false;␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27)) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); ␊ |
␉␉␉␉␉␉␉delay(1);␊ |
␉␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉break;␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);␊ |
␉␉␉␉␉␉maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);␊ |
␉␉␉␉␉␉minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉if (minimum.FID == 0) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉uint64_t msr;␊ |
␉␉␉␉␉␉␉uint8_t i;␊ |
␉␉␉␉␉␉␉// Probe for lowest fid␊ |
␉␉␉␉␉␉␉for (i = maximum.FID; i >= 0x6; i--) ␊ |
␉␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
␉␉␉␉␉␉␉␉delay(1);␊ |
␉␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉if (minimum.VID == maximum.VID) ␊ |
␉␉␉␉␉␉{␉␊ |
␉␉␉␉␉␉␉uint64_t msr;␊ |
␉␉␉␉␉␉␉uint8_t i;␊ |
␉␉␉␉␉␉␉// Probe for lowest vid␊ |
␉␉␉␉␉␉␉for (i = maximum.VID; i > 0xA; i--) ␊ |
␉␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
␉␉␉␉␉␉␉␉delay(1);␊ |
␉␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉// Sanity check␊ |
␉␉␉␉␉␉if (maximum.CID < minimum.CID) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉DBG("Insane FID values!");␊ |
␉␉␉␉␉␉␉p_states_count = 1;␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉else␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉// Finalize P-States␊ |
␉␉␉␉␉␉␉// Find how many P-States machine supports␊ |
␉␉␉␉␉␉␉p_states_count = maximum.CID - minimum.CID + 1;␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉if (p_states_count > 32) ␊ |
␉␉␉␉␉␉␉␉p_states_count = 32;␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉uint8_t vidstep;␊ |
␉␉␉␉␉␉␉uint8_t i = 0, u, invalid = 0;␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉for (u = 0; u < p_states_count; u++) ␊ |
␉␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉␉i = u - invalid;␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉p_states[i].CID = maximum.CID - u;␊ |
␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].CID >> 1);␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉if (p_states[i].FID < 0x6) ␊ |
␉␉␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉␉␉if (cpu_dynamic_fsb) ␊ |
␉␉␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].FID << 1) | 0x80;␊ |
␉␉␉␉␉␉␉␉} ␊ |
␉␉␉␉␉␉␉␉else if (cpu_noninteger_bus_ratio) ␊ |
␉␉␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉␉␉p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));␊ |
␉␉␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉if (i && p_states[i].FID == p_states[i-1].FID)␊ |
␉␉␉␉␉␉␉␉␉invalid++;␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉uint32_t multiplier = p_states[i].FID & 0x1f;␉␉// = 0x08␊ |
␉␉␉␉␉␉␉␉bool half = p_states[i].FID & 0x40;␉␉␉␉␉// = 0x01␊ |
␉␉␉␉␉␉␉␉bool dfsb = p_states[i].FID & 0x80;␉␉␉␉␉// = 0x00␊ |
␉␉␉␉␉␉␉␉uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400␊ |
␉␉␉␉␉␉␉␉uint32_t halffsb = (fsb + 1) >> 1;␉␉␉␉␉// = 200␊ |
␉␉␉␉␉␉␉␉uint32_t frequency = (multiplier * fsb);␉␉␉// = 3200␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;␉// = 3200 + 200 = 3400␊ |
␉␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉p_states_count -= invalid;␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉} break;␊ |
␉␉␉␉␉case 0x1A: // Intel Core i7 LGA1366 (45nm)␊ |
␉␉␉␉␉case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)␊ |
␉␉␉␉␉case 0x1F:␊ |
␉␉␉␉␉case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)␊ |
␉␉␉␉␉case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core␊ |
␉␉␉␉␉case 0x2F:␊ |
␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 15);␊ |
␉␉␉␉␉default:␊ |
␉␉␉␉␉␉verbose ("Unsupported CPU: P-States not generated !!!\n");␊ |
␉␉␉␉␉␉break;␊ |
␉␉␉␉}␊ |
␉␉␉}␊ |
␉␉}␊ |
␉␉␊ |
␉␉initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
␉␉␊ |
␉␉maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);␊ |
␉␉maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;␊ |
␉␉␊ |
␉␉minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);␊ |
␉␉minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);␊ |
␉␉␊ |
␉␉if (minimum.FID == 0) ␊ |
␉␉{␊ |
␉␉␉uint64_t msr;␊ |
␉␉␉uint8_t i;␊ |
␉␉␉// Probe for lowest fid␊ |
␉␉␉for (i = maximum.FID; i >= 0x6; i--) ␊ |
␉␉␉{␊ |
␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
␉␉␉␉delay(1);␊ |
␉␉␉}␊ |
␉␉␉␊ |
␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉intel_waitforsts();␊ |
␉␉}␊ |
␉␉␊ |
␉␉if (minimum.VID == maximum.VID) ␊ |
␉␉{␉␊ |
␉␉␉uint64_t msr;␊ |
␉␉␉uint8_t i;␊ |
␉␉␉// Probe for lowest vid␊ |
␉␉␉for (i = maximum.VID; i > 0xA; i--) ␊ |
␉␉␉{␊ |
␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
␉␉␉␉delay(1);␊ |
␉␉␉}␊ |
␉␉␉␊ |
␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉intel_waitforsts();␊ |
␉␉}␊ |
␉␉␊ |
␉␉minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;␊ |
␉␉␊ |
␉␉// Sanity check␊ |
␉␉if (maximum.CID < minimum.CID) ␊ |
␉␉{␊ |
␉␉␉DBG("Insane FID values!");␊ |
␉␉␉p_states_count = 1;␊ |
␉␉}␊ |
␉␉else␊ |
␉␉{␊ |
␉␉␉// Finalize P-States␊ |
␉␉␉// Find how many P-States machine supports␊ |
␉␉␉p_states_count = maximum.CID - minimum.CID + 1;␊ |
␉␉␉␊ |
␉␉␉if (p_states_count > 32) ␊ |
␉␉␉␉p_states_count = 32;␊ |
␉␉␉␊ |
␉␉␉uint8_t vidstep;␊ |
␉␉␉uint8_t i = 0, u, invalid = 0;␊ |
␉␉␉␊ |
␉␉␉vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);␊ |
␉␉␉␊ |
␉␉␉for (u = 0; u < p_states_count; u++) ␊ |
␉␉␉{␊ |
␉␉␉␉i = u - invalid;␊ |
␉␉␉␉␊ |
␉␉␉␉p_states[i].CID = maximum.CID - u;␊ |
␉␉␉␉p_states[i].FID = (p_states[i].CID >> 1);␊ |
␉␉␉␉␊ |
␉␉␉␉if (p_states[i].FID < 0x6) ␊ |
␉␉␉␉{␊ |
␉␉␉␉␉if (cpu_dynamic_fsb) ␊ |
␉␉␉␉␉␉p_states[i].FID = (p_states[i].FID << 1) | 0x80;␊ |
␉␉␉␉} ␊ |
␉␉␉␉else if (cpu_noninteger_bus_ratio) ␊ |
␉␉␉␉{␊ |
␉␉␉␉␉p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));␊ |
␉␉␉␉}␊ |
␉␉␉␉␊ |
␉␉␉␉if (i && p_states[i].FID == p_states[i-1].FID)␊ |
␉␉␉␉␉invalid++;␊ |
␉␉␉␉␊ |
␉␉␉␉p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;␊ |
␉␉␉␉␊ |
␉␉␉␉uint32_t multiplier = p_states[i].FID & 0x1f;␉␉// = 0x08␊ |
␉␉␉␉bool half = p_states[i].FID & 0x40;␉␉␉␉␉// = 0x01␊ |
␉␉␉␉bool dfsb = p_states[i].FID & 0x80;␉␉␉␉␉// = 0x00␊ |
␉␉␉␉uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400␊ |
␉␉␉␉uint32_t halffsb = (fsb + 1) >> 1;␉␉␉␉␉// = 200␊ |
␉␉␉␉uint32_t frequency = (multiplier * fsb);␉␉␉// = 3200␊ |
␉␉␉␉␊ |
␉␉␉␉p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;␉// = 3200 + 200 = 3400␊ |
␉␉␉}␊ |
␉␉␉␊ |
␉␉␉p_states_count -= invalid;␊ |
␉␉}␊ |
␉␉␊ |
␉␉// Generating SSDT␊ |
␉␉␊ |
␉␉if (p_states_count > 0) ␊ |
|
␉␉␉return ssdt;␊ |
␉␉}␊ |
␉}␊ |
␉else {␊ |
␉else ␊ |
␉{␊ |
␉␉verbose ("ACPI CPUs not found: P-States not generated !!!\n");␊ |
␉}␊ |
␉␊ |