Root/
Source at commit HEAD created 5 years 6 days ago. By ifabio, Few update to kernelPatcher (Credits to CrazyBirdy) | |
---|---|
1 | /*␊ |
2 | * Copyright 2008 mackerintel␊ |
3 | *␊ |
4 | * state_generator.h␊ |
5 | * Chameleon␊ |
6 | *␊ |
7 | * Created by Mozodojo on 20/07/10.␊ |
8 | * Copyright 2010 mozodojo. All rights reserved.␊ |
9 | *␊ |
10 | */␊ |
11 | ␊ |
12 | #include "config.h"␊ |
13 | #include "libsaio.h"␊ |
14 | #include "boot.h"␊ |
15 | #include "bootstruct.h"␊ |
16 | #include "acpi.h"␊ |
17 | #include "efi_tables.h"␊ |
18 | #include "fake_efi.h"␊ |
19 | #include "acpi_patcher.h"␊ |
20 | #include "platform.h"␊ |
21 | #include "cpu.h"␊ |
22 | #include "aml_generator.h"␊ |
23 | #include "state_generator.h"␊ |
24 | ␊ |
25 | #if DEBUG_STATE==2␊ |
26 | #define DBG(x...) {printf(x); sleep(1);}␊ |
27 | #elif DEBUG_STATE==1␊ |
28 | ␉#define DBG(x...) printf(x)␊ |
29 | #else␊ |
30 | ␉#define DBG(x...) msglog(x)␊ |
31 | #endif␊ |
32 | ␊ |
33 | uint8_t acpi_cpu_count␉= 0;␊ |
34 | uint32_t acpi_cpu_p_blk␉= 0;␊ |
35 | char *acpi_cpu_name[32];␊ |
36 | ␊ |
37 | void get_acpi_cpu_names(unsigned char *dsdt, uint32_t length)␊ |
38 | {␊ |
39 | ␉uint32_t i;␊ |
40 | ␊ |
41 | ␉DBG("\tACPI patcher: start finding cpu names. Length %d\n", length);␊ |
42 | ␊ |
43 | ␉for (i=0; i<length-7; i++)␊ |
44 | ␉{␊ |
45 | ␉␉if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP␊ |
46 | ␉␉{␊ |
47 | ␉␉␉DBG("\tACPIpatcher: DSDT[%X%X]\n", dsdt[i], dsdt[i+1]);␊ |
48 | ␊ |
49 | ␉␉␉uint32_t offset = i + 3 + (dsdt[i+2] >> 6);␊ |
50 | ␊ |
51 | ␉␉␉bool add_name = true;␊ |
52 | ␊ |
53 | ␉␉␉uint8_t j;␊ |
54 | ␊ |
55 | ␉␉␉for (j=0; j<4; j++)␊ |
56 | ␉␉␉{␊ |
57 | ␉␉␉␉char c = dsdt[offset+j];␊ |
58 | ␊ |
59 | ␉␉␉␉if (!aml_isvalidchar(c))␊ |
60 | ␉␉␉␉{␊ |
61 | ␉␉␉␉␉add_name = false;␊ |
62 | ␉␉␉␉␉DBG("\tACPI patcher: invalid character found in ProcessorOP '0x%X'!\n", c);␊ |
63 | ␉␉␉␉␉break;␊ |
64 | ␉␉␉␉}␊ |
65 | ␉␉␉}␊ |
66 | ␊ |
67 | ␉␉␉if (add_name)␊ |
68 | ␉␉␉{␊ |
69 | ␉␉␉␉acpi_cpu_name[acpi_cpu_count] = malloc(4);␊ |
70 | ␉␉␉␉memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);␊ |
71 | ␉␉␉␉i = offset + 5;␊ |
72 | ␊ |
73 | ␉␉␉␉if (acpi_cpu_count == 0)␊ |
74 | ␉␉␉␉{␊ |
75 | ␉␉␉␉␉acpi_cpu_p_blk = dsdt[i] | (dsdt[i+1] << 8);␊ |
76 | ␉␉␉␉}␊ |
77 | ␊ |
78 | ␉␉␉␉DBG("\tACPI patcher: found ACPI CPU [%c%c%c%c]\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);␊ |
79 | ␊ |
80 | ␉␉␉␉if (++acpi_cpu_count == 32)␊ |
81 | ␉␉␉␉{␊ |
82 | ␉␉␉␉␉return;␊ |
83 | ␉␉␉␉}␊ |
84 | ␉␉␉}␊ |
85 | ␉␉}␊ |
86 | ␉}␊ |
87 | ␊ |
88 | ␉DBG("\tACPIpatcher: finished finding cpu names. Found: %d.\n", acpi_cpu_count);␊ |
89 | }␊ |
90 | ␊ |
91 | static char const pss_ssdt_header[] =␊ |
92 | {␊ |
93 | ␉0x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
94 | ␉0x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */␊ |
95 | ␉0x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */␊ |
96 | ␉0x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */␊ |
97 | ␉0x31, 0x03, 0x10, 0x20,␉␉␉␉/* 1.._␉␉*/␊ |
98 | };␊ |
99 | ␊ |
100 | static char const cst_ssdt_header[] =␊ |
101 | {␊ |
102 | ␉0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
103 | ␉0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */␊ |
104 | ␉0x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */␊ |
105 | ␉0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */␊ |
106 | ␉0x31, 0x03, 0x10, 0x20␉␉␉␉/* 1.._␉␉*/␊ |
107 | };␊ |
108 | ␊ |
109 | char resource_template_register_fixedhw[] =␊ |
110 | {␊ |
111 | ␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,␊ |
112 | ␉0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,␊ |
113 | ␉0x00, 0x00, 0x01, 0x79, 0x00␊ |
114 | };␊ |
115 | ␊ |
116 | char resource_template_register_systemio[] =␊ |
117 | {␊ |
118 | ␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x01,␊ |
119 | ␉0x08, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, 0x00,␊ |
120 | ␉0x00, 0x00, 0x00, 0x79, 0x00,␊ |
121 | };␊ |
122 | ␊ |
123 | struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt *dsdt)␊ |
124 | {␊ |
125 | ␉verbose("[ GENERATE P-STATES ]\n");␊ |
126 | ␊ |
127 | ␉if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) // 0x756E6547␊ |
128 | ␉{␊ |
129 | ␉␉DBG("\tNot an Intel platform: P-States will not be generated !!!\n");␊ |
130 | ␉␉return NULL;␊ |
131 | ␉}␊ |
132 | ␊ |
133 | ␉if (!(Platform.CPU.Features & CPU_FEATURE_MSR))␊ |
134 | ␉{␊ |
135 | ␉␉DBG("\tUnsupported CPU: P-States will not be generated !!! No MSR support\n");␊ |
136 | ␉␉return NULL;␊ |
137 | ␉}␊ |
138 | ␊ |
139 | ␉if (acpi_cpu_count == 0)␊ |
140 | ␉{␊ |
141 | ␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
142 | ␉}␊ |
143 | ␊ |
144 | ␉if (acpi_cpu_count > 0)␊ |
145 | ␉{␊ |
146 | ␉␉struct p_state initial, maximum, minimum, p_states[32];␊ |
147 | ␉␉uint8_t p_states_count = 0;␊ |
148 | ␊ |
149 | ␉␉// Retrieving P-States, ported from code by superhai (c)␊ |
150 | ␉␉switch (Platform.CPU.Family)␊ |
151 | ␉␉{␊ |
152 | ␉␉␉case 0x06:␊ |
153 | ␉␉␉{␊ |
154 | ␉␉␉␉switch (Platform.CPU.Model)␊ |
155 | ␉␉␉␉{␊ |
156 | ␉␉␉␉␉case CPUID_MODEL_DOTHAN:␉// Intel Pentium M␊ |
157 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␉␉// Intel Mobile Core Solo, Duo␊ |
158 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␉␉// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx␊ |
159 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␉// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx␊ |
160 | ␉␉␉␉␉case CPUID_MODEL_ATOM:␉␉// Intel Atom (45nm)␊ |
161 | ␉␉␉␉␉{␊ |
162 | ␉␉␉␉␉␉bool cpu_dynamic_fsb = false;␊ |
163 | ␊ |
164 | ␉␉␉␉␉␉if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))␊ |
165 | ␉␉␉␉␉␉{␊ |
166 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); ␊ |
167 | ␉␉␉␉␉␉␉delay(1);␊ |
168 | ␉␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);␊ |
169 | ␉␉␉␉␉␉}␊ |
170 | ␊ |
171 | ␉␉␉␉␉␉bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));␊ |
172 | ␊ |
173 | ␉␉␉␉␉␉initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
174 | ␊ |
175 | ␉␉␉␉␉␉maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);␊ |
176 | ␉␉␉␉␉␉maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;␊ |
177 | ␊ |
178 | ␉␉␉␉␉␉minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);␊ |
179 | ␉␉␉␉␉␉minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);␊ |
180 | ␊ |
181 | ␉␉␉␉␉␉if (minimum.FID == 0)␊ |
182 | ␉␉␉␉␉␉{␊ |
183 | ␉␉␉␉␉␉␉uint64_t msr;␊ |
184 | ␉␉␉␉␉␉␉uint8_t i;␊ |
185 | ␉␉␉␉␉␉␉// Probe for lowest fid␊ |
186 | ␉␉␉␉␉␉␉for (i = maximum.FID; i >= 0x6; i--)␊ |
187 | ␉␉␉␉␉␉␉{␊ |
188 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
189 | ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
190 | ␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
191 | ␉␉␉␉␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
192 | ␉␉␉␉␉␉␉␉delay(1);␊ |
193 | ␉␉␉␉␉␉␉}␊ |
194 | ␊ |
195 | ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
196 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
197 | ␉␉␉␉␉␉␉intel_waitforsts();␊ |
198 | ␉␉␉␉␉␉}␊ |
199 | ␊ |
200 | ␉␉␉␉␉␉if (minimum.VID == maximum.VID) ␊ |
201 | ␉␉␉␉␉␉{␊ |
202 | ␉␉␉␉␉␉␉uint64_t msr;␊ |
203 | ␉␉␉␉␉␉␉uint8_t i;␊ |
204 | ␉␉␉␉␉␉␉// Probe for lowest vid␊ |
205 | ␉␉␉␉␉␉␉for (i = maximum.VID; i > 0xA; i--) ␊ |
206 | ␉␉␉␉␉␉␉{␊ |
207 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
208 | ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
209 | ␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
210 | ␉␉␉␉␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
211 | ␉␉␉␉␉␉␉␉delay(1);␊ |
212 | ␉␉␉␉␉␉␉}␊ |
213 | ␊ |
214 | ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
215 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
216 | ␉␉␉␉␉␉␉intel_waitforsts();␊ |
217 | ␉␉␉␉␉␉}␊ |
218 | ␊ |
219 | ␉␉␉␉␉␉minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;␊ |
220 | ␊ |
221 | ␉␉␉␉␉␉// Sanity check␊ |
222 | ␉␉␉␉␉␉if (maximum.CID < minimum.CID)␊ |
223 | ␉␉␉␉␉␉{␊ |
224 | ␉␉␉␉␉␉␉DBG("\tP-States: Insane FID values!");␊ |
225 | ␉␉␉␉␉␉␉p_states_count = 0;␊ |
226 | ␉␉␉␉␉␉}␊ |
227 | ␉␉␉␉␉␉else␊ |
228 | ␉␉␉␉␉␉{␊ |
229 | ␉␉␉␉␉␉␉uint8_t vidstep;␊ |
230 | ␉␉␉␉␉␉␉uint8_t u, invalid = 0;␊ |
231 | ␉␉␉␉␉␉␉// Finalize P-States␊ |
232 | ␉␉␉␉␉␉␉// Find how many P-States machine supports␊ |
233 | ␉␉␉␉␉␉␉p_states_count = (uint8_t)(maximum.CID - minimum.CID + 1);␊ |
234 | ␊ |
235 | ␉␉␉␉␉␉␉if (p_states_count > 32)␊ |
236 | ␉␉␉␉␉␉␉{␊ |
237 | ␉␉␉␉␉␉␉␉p_states_count = 32;␊ |
238 | ␉␉␉␉␉␉␉}␊ |
239 | ␉␉␉␉␉␉␉DBG("\tPStates count=%d\n", p_states_count);␊ |
240 | ␊ |
241 | ␉␉␉␉␉␉␉vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);␊ |
242 | ␊ |
243 | ␉␉␉␉␉␉␉for (u = 0; u < p_states_count; u++)␊ |
244 | ␉␉␉␉␉␉␉{␊ |
245 | ␉␉␉␉␉␉␉␉uint8_t i = u - invalid;␊ |
246 | ␊ |
247 | ␉␉␉␉␉␉␉␉p_states[i].CID = maximum.CID - u;␊ |
248 | ␉␉␉␉␉␉␉␉p_states[i].FID = (uint8_t)(p_states[i].CID >> 1);␊ |
249 | ␊ |
250 | ␉␉␉␉␉␉␉␉if (p_states[i].FID < 0x6)␊ |
251 | ␉␉␉␉␉␉␉␉{␊ |
252 | ␉␉␉␉␉␉␉␉␉if (cpu_dynamic_fsb)␊ |
253 | ␉␉␉␉␉␉␉␉␉{␊ |
254 | ␉␉␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].FID << 1) | 0x80;␊ |
255 | ␉␉␉␉␉␉␉␉␉}␊ |
256 | ␉␉␉␉␉␉␉␉}␊ |
257 | ␉␉␉␉␉␉␉␉else if (cpu_noninteger_bus_ratio)␊ |
258 | ␉␉␉␉␉␉␉␉{␊ |
259 | ␉␉␉␉␉␉␉␉␉p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));␊ |
260 | ␉␉␉␉␉␉␉␉}␊ |
261 | ␊ |
262 | ␉␉␉␉␉␉␉␉if (i && p_states[i].FID == p_states[i-1].FID)␊ |
263 | ␉␉␉␉␉␉␉␉{␊ |
264 | ␉␉␉␉␉␉␉␉␉invalid++;␊ |
265 | ␉␉␉␉␉␉␉␉}␊ |
266 | ␉␉␉␉␉␉␉␉p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;␊ |
267 | ␉␉␉␉␉␉␉␉uint32_t multiplier = p_states[i].FID & 0x1f;␉␉// = 0x08␊ |
268 | ␉␉␉␉␉␉␉␉bool half = p_states[i].FID & 0x40;␉␉␉␉␉// = 0x01␊ |
269 | ␉␉␉␉␉␉␉␉bool dfsb = p_states[i].FID & 0x80;␉␉␉␉␉// = 0x00␊ |
270 | ␉␉␉␉␉␉␉␉uint32_t fsb = (uint32_t)(Platform.CPU.FSBFrequency / 1000000); // = 400␊ |
271 | ␉␉␉␉␉␉␉␉uint32_t halffsb = (fsb + 1) >> 1;␉␉␉␉␉// = 200␊ |
272 | ␉␉␉␉␉␉␉␉uint32_t frequency = (multiplier * fsb);␉␉␉// = 3200␊ |
273 | ␊ |
274 | ␉␉␉␉␉␉␉␉p_states[i].Frequency = (uint32_t)(frequency + (half * halffsb)) >> dfsb;␉// = 3200 + 200 = 3400␊ |
275 | ␉␉␉␉␉␉␉}␊ |
276 | ␊ |
277 | ␉␉␉␉␉␉␉p_states_count -= invalid;␊ |
278 | ␉␉␉␉␉␉}␊ |
279 | ␊ |
280 | ␉␉␉␉␉␉break;␊ |
281 | ␉␉␉␉␉}␊ |
282 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␉␉// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)␊ |
283 | ␉␉␉␉␉case CPUID_MODEL_CLARKDALE:␉␉//␊ |
284 | ␉␉␉␉␉case CPUID_MODEL_DALES:␉␉␉// Intel Core i3, i5 LGA1156 (32nm)␊ |
285 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␉␉// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)␊ |
286 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␉␉// Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65xx␊ |
287 | ␉␉␉␉␉case CPUID_MODEL_WESTMERE:␉␉// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core␊ |
288 | ␉␉␉␉␉case CPUID_MODEL_WESTMERE_EX:␉␉// Intel Xeon E7␊ |
289 | ␉␉␉␉␉case CPUID_MODEL_SANDYBRIDGE:␉␉// Intel Core i3, i5, i7 LGA1155 (32nm)␊ |
290 | ␉␉␉␉␉case CPUID_MODEL_JAKETOWN:␉␉// Intel Core i7, Xeon E5 LGA2011 (32nm)␊ |
291 | ␉␉␉␉␉case CPUID_MODEL_IVYBRIDGE:␉␉// Intel Core i3, i5, i7 LGA1155 (22nm)␊ |
292 | ␉␉␉␉␉case CPUID_MODEL_HASWELL:␉␉//␊ |
293 | ␉␉␉␉␉case CPUID_MODEL_IVYBRIDGE_XEON:␉//␊ |
294 | ␉␉␉␉␉//case CPUID_MODEL_HASWELL_H:␉␉//␊ |
295 | ␉␉␉␉␉case CPUID_MODEL_HASWELL_SVR:␉␉//␊ |
296 | ␉␉␉␉␉case CPUID_MODEL_HASWELL_ULT:␉␉//␊ |
297 | ␉␉␉␉␉case CPUID_MODEL_HASWELL_ULX:␉␉//␊ |
298 | ␉␉␉␉␉case CPUID_MODEL_BROADWELL_HQ:␊ |
299 | ␉␉␉␉␉case CPUID_MODEL_SKYLAKE_S:␊ |
300 | ␉␉␉␉␉case CPUID_MODEL_ATOM_3700:␊ |
301 | ␊ |
302 | ␉␉␉␉␉{␊ |
303 | ␉␉␉␉␉if ( (Platform.CPU.Model == CPUID_MODEL_SANDYBRIDGE) ||␊ |
304 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_JAKETOWN) ||␊ |
305 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_IVYBRIDGE) ||␊ |
306 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL) ||␊ |
307 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_IVYBRIDGE_XEON) ||␊ |
308 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL_SVR) ||␊ |
309 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL_ULT) ||␊ |
310 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL_ULX) ||␊ |
311 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_ATOM_3700) )␊ |
312 | ␉␉␉␉␉{␊ |
313 | ␉␉␉␉␉␉maximum.Control = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0xff;␊ |
314 | ␉␉␉␉␉}␊ |
315 | ␉␉␉␉␉else␊ |
316 | ␉␉␉␉␉{␊ |
317 | ␉␉␉␉␉␉maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff;␊ |
318 | ␉␉␉␉␉}␊ |
319 | ␊ |
320 | ␉␉␉␉␉minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;␊ |
321 | ␊ |
322 | ␉␉␉␉␉DBG("\tP-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);␊ |
323 | ␊ |
324 | ␉␉␉␉␉// Sanity check␊ |
325 | ␉␉␉␉␉if (maximum.Control < minimum.Control)␊ |
326 | ␉␉␉␉␉{␊ |
327 | ␉␉␉␉␉␉DBG("\tInsane control values!");␊ |
328 | ␉␉␉␉␉␉p_states_count = 0;␊ |
329 | ␉␉␉␉␉}␊ |
330 | ␉␉␉␉␉else␊ |
331 | ␉␉␉␉␉{␊ |
332 | ␉␉␉␉␉␉uint8_t i;␊ |
333 | ␉␉␉␉␉␉p_states_count = 0;␊ |
334 | ␊ |
335 | ␉␉␉␉␉␉for (i = maximum.Control; i >= minimum.Control; i--)␊ |
336 | ␉␉␉␉␉␉{␊ |
337 | ␉␉␉␉␉␉␉p_states[p_states_count].Control = i;␊ |
338 | ␉␉␉␉␉␉␉p_states[p_states_count].CID = p_states[p_states_count].Control << 1;␊ |
339 | ␉␉␉␉␉␉␉p_states[p_states_count].Frequency = (Platform.CPU.FSBFrequency / 1000000) * i;␊ |
340 | ␉␉␉␉␉␉␉p_states_count++;␊ |
341 | ␉␉␉␉␉␉}␊ |
342 | ␉␉␉␉␉}␊ |
343 | ␊ |
344 | ␉␉␉␉␉break;␊ |
345 | ␉␉␉␉}␊ |
346 | ␉␉␉␉default:␊ |
347 | ␉␉␉␉␉DBG("\tUnsupported CPU (0x%X): P-States not generated !!!\n", Platform.CPU.Family);␊ |
348 | ␉␉␉␉␉break;␊ |
349 | ␉␉␉}␊ |
350 | ␉␉}␊ |
351 | ␉}␊ |
352 | ␊ |
353 | ␉// Generating SSDT␊ |
354 | ␉if (p_states_count > 0)␊ |
355 | ␉{␊ |
356 | ␊ |
357 | ␉␉int i;␊ |
358 | ␊ |
359 | ␉␉AML_CHUNK *root = aml_create_node(NULL);␊ |
360 | ␉␉aml_add_buffer(root, pss_ssdt_header, sizeof(pss_ssdt_header)); // SSDT header␊ |
361 | ␊ |
362 | ␉␉AML_CHUNK *scop = aml_add_scope(root, "\\_PR_");␊ |
363 | ␉␉AML_CHUNK *name = aml_add_name(scop, "PSS_");␊ |
364 | ␉␉AML_CHUNK *pack = aml_add_package(name);␊ |
365 | ␊ |
366 | ␉␉for (i = 0; i < p_states_count; i++)␊ |
367 | ␉␉{␊ |
368 | ␉␉␉AML_CHUNK *pstt = aml_add_package(pack);␊ |
369 | ␊ |
370 | ␉␉␉aml_add_dword(pstt, p_states[i].Frequency);␊ |
371 | ␉␉␉aml_add_dword(pstt, 0x00000000); // Power␊ |
372 | ␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
373 | ␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
374 | ␉␉␉aml_add_dword(pstt, p_states[i].Control);␊ |
375 | ␉␉␉aml_add_dword(pstt, i+1); // Status␊ |
376 | ␉␉}␊ |
377 | ␊ |
378 | ␉␉␉// Add aliaces CPUs␊ |
379 | ␉␉␉for (i = 0; i < acpi_cpu_count; i++)␊ |
380 | ␉␉␉{␊ |
381 | ␉␉␉␉char name[9];␊ |
382 | ␉␉␉␉sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);␊ |
383 | ␊ |
384 | ␉␉␉␉scop = aml_add_scope(root, name);␊ |
385 | ␉␉␉␉aml_add_alias(scop, "PSS_", "_PSS");␊ |
386 | ␉␉␉}␊ |
387 | ␊ |
388 | ␉␉␉aml_calculate_size(root);␊ |
389 | ␊ |
390 | ␉␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
391 | ␊ |
392 | ␉␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
393 | ␊ |
394 | ␉␉␉ssdt->Length = root->Size;␊ |
395 | ␉␉␉ssdt->Checksum = 0;␊ |
396 | ␉␉␉ssdt->Checksum = (uint8_t)(256 - checksum8(ssdt, ssdt->Length));␊ |
397 | ␊ |
398 | ␉␉␉aml_destroy_node(root);␊ |
399 | ␊ |
400 | ␉␉␉//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);␊ |
401 | ␊ |
402 | ␉␉␉DBG("\tSSDT with CPU P-States generated successfully\n");␊ |
403 | ␊ |
404 | ␉␉␉return ssdt;␊ |
405 | ␉␉}␊ |
406 | ␉}␊ |
407 | ␉else␊ |
408 | ␉{␊ |
409 | ␉␉DBG("\tACPI CPUs not found: P-States not generated !!!\n");␊ |
410 | ␉}␊ |
411 | ␊ |
412 | ␉verbose("\n");␊ |
413 | ␊ |
414 | ␉return NULL;␊ |
415 | }␊ |
416 | ␊ |
417 | struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt *fadt)␊ |
418 | {␊ |
419 | ␉verbose("[ GENERATE C-STATES ]\n");␊ |
420 | ␊ |
421 | ␉if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) // 0x756E6547␊ |
422 | ␉{␊ |
423 | ␉␉DBG("\tNot an Intel platform: C-States will not be generated !!!\n");␊ |
424 | ␉␉return NULL;␊ |
425 | ␉}␊ |
426 | ␊ |
427 | ␉if (fadt == NULL)␊ |
428 | ␉{␊ |
429 | ␉␉DBG("\tFACP not exists: C-States will not be generated !!!\n");␊ |
430 | ␉␉return NULL;␊ |
431 | ␉}␊ |
432 | ␊ |
433 | ␉struct acpi_2_dsdt *dsdt = (void *)fadt->DSDT;␊ |
434 | ␊ |
435 | ␉if (dsdt == NULL)␊ |
436 | ␉{␊ |
437 | ␉␉DBG("\tDSDT not found: C-States will not be generated !!!\n");␊ |
438 | ␉␉return NULL;␊ |
439 | ␉}␊ |
440 | ␊ |
441 | ␉if (acpi_cpu_count == 0)␊ |
442 | ␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
443 | ␊ |
444 | ␉if (acpi_cpu_count > 0)␊ |
445 | ␉{␊ |
446 | ␉␉bool c2_enabled = false;␊ |
447 | ␉␉bool c3_enabled = false;␊ |
448 | ␉␉bool c4_enabled = false;␊ |
449 | ␉␉bool c6_enabled = false;␊ |
450 | ␉␉bool c7_enabled = false;␊ |
451 | ␉␉bool cst_using_systemio = false;␊ |
452 | ␊ |
453 | ␉␉getBoolForKey(kEnableC2State, &c2_enabled, &bootInfo->chameleonConfig);␊ |
454 | ␉␉getBoolForKey(kEnableC3State, &c3_enabled, &bootInfo->chameleonConfig);␊ |
455 | ␉␉getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->chameleonConfig);␊ |
456 | ␉␉getBoolForKey(kEnableC6State, &c6_enabled, &bootInfo->chameleonConfig);␊ |
457 | ␉␉getBoolForKey(kEnableC7State, &c7_enabled, &bootInfo->chameleonConfig);␊ |
458 | ␉␉getBoolForKey(kCSTUsingSystemIO, &cst_using_systemio, &bootInfo->chameleonConfig);␊ |
459 | ␊ |
460 | ␉␉c2_enabled = c2_enabled | (fadt->C2_Latency < 100);␊ |
461 | ␉␉c3_enabled = c3_enabled | (fadt->C3_Latency < 1000);␊ |
462 | ␊ |
463 | ␉␉unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + ((c3_enabled || c4_enabled)? 1 : 0) + (c6_enabled ? 1 : 0) + (c7_enabled ? 1 : 0);␊ |
464 | ␊ |
465 | ␉␉AML_CHUNK* root = aml_create_node(NULL);␊ |
466 | ␉␉aml_add_buffer(root, cst_ssdt_header, sizeof(cst_ssdt_header)); // SSDT header␊ |
467 | ␉␉AML_CHUNK* scop = aml_add_scope(root, "\\_PR_");␊ |
468 | ␉␉AML_CHUNK* name = aml_add_name(scop, "CST_");␊ |
469 | ␉␉AML_CHUNK* pack = aml_add_package(name);␊ |
470 | ␉␉aml_add_byte(pack, cstates_count);␊ |
471 | ␊ |
472 | ␉␉AML_CHUNK* tmpl = aml_add_package(pack);␊ |
473 | ␉␉if (cst_using_systemio)␊ |
474 | ␉␉{␊ |
475 | ␉␉␉// C1␊ |
476 | ␉␉␉resource_template_register_fixedhw[8] = 0x00;␊ |
477 | ␉␉␉resource_template_register_fixedhw[9] = 0x00;␊ |
478 | ␉␉␉resource_template_register_fixedhw[18] = 0x00;␊ |
479 | ␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
480 | ␉␉␉aml_add_byte(tmpl, 0x01);␉␉// C1␊ |
481 | ␉␉␉aml_add_word(tmpl, 0x0001);␉␉// Latency␊ |
482 | ␉␉␉aml_add_dword(tmpl, 0x000003e8);␉// Power␊ |
483 | ␊ |
484 | ␉␉␉uint8_t p_blk_lo, p_blk_hi;␊ |
485 | ␊ |
486 | ␉␉␉if (c2_enabled) // C2␊ |
487 | ␉␉␉{␊ |
488 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 4;␊ |
489 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 4) >> 8;␊ |
490 | ␊ |
491 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
492 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C2␊ |
493 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C2␊ |
494 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
495 | ␉␉␉␉aml_add_byte(tmpl, 0x02);␉␉// C2␊ |
496 | ␉␉␉␉aml_add_word(tmpl, 0x0040);␉␉// Latency␊ |
497 | ␉␉␉␉aml_add_dword(tmpl, 0x000001f4);␉// Power␊ |
498 | ␉␉␉}␊ |
499 | ␊ |
500 | ␉␉␉if (c4_enabled) // C4␊ |
501 | ␉␉␉{␊ |
502 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
503 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
504 | ␊ |
505 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
506 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C4␊ |
507 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C4␊ |
508 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
509 | ␉␉␉␉aml_add_byte(tmpl, 0x04);␉␉// C4␊ |
510 | ␉␉␉␉aml_add_word(tmpl, 0x0080);␉␉// Latency␊ |
511 | ␉␉␉␉aml_add_dword(tmpl, 0x000000C8);␉// Power␊ |
512 | ␉␉␉}␊ |
513 | ␉␉␉else if (c3_enabled) // C3␊ |
514 | ␉␉␉{␊ |
515 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
516 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
517 | ␊ |
518 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
519 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C3␊ |
520 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C3␊ |
521 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
522 | ␉␉␉␉aml_add_byte(tmpl, 0x03);␉␉// C3␊ |
523 | ␉␉␉␉aml_add_word(tmpl, 0x0043);␉␉// Latency␊ |
524 | ␉␉␉␉aml_add_dword(tmpl, 0x000001F4);␉// Power␊ |
525 | ␉␉␉}␊ |
526 | ␉␉␉if (c6_enabled) // C6␊ |
527 | ␉␉␉{␊ |
528 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
529 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
530 | ␊ |
531 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
532 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C6␊ |
533 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C6␊ |
534 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
535 | ␉␉␉␉aml_add_byte(tmpl, 0x06);␉␉␉// C6␊ |
536 | ␉␉␉␉aml_add_word(tmpl, 0x0046);␉␉␉// Latency␊ |
537 | ␉␉␉␉aml_add_dword(tmpl, 0x0000015E);␉␉// Power␊ |
538 | ␉␉␉}␊ |
539 | ␉␉␉if (c7_enabled) //C7␊ |
540 | ␉␉␉{␊ |
541 | ␉␉␉␉p_blk_lo = (acpi_cpu_p_blk + 6) & 0xff;␊ |
542 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
543 | ␊ |
544 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
545 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C4 or C7␊ |
546 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi;␊ |
547 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
548 | ␉␉␉␉aml_add_byte(tmpl, 0x07);␉␉␉// C7␊ |
549 | ␉␉␉␉aml_add_word(tmpl, 0xF5);␉␉␉// Latency as in iMac14,1␊ |
550 | ␉␉␉␉aml_add_dword(tmpl, 0xC8);␉␉␉// Power␊ |
551 | ␉␉␉}␊ |
552 | ␉␉}␊ |
553 | ␉␉else␊ |
554 | ␉␉{␊ |
555 | ␉␉␉// C1␊ |
556 | ␉␉␉resource_template_register_fixedhw[8] = 0x01;␊ |
557 | ␉␉␉resource_template_register_fixedhw[9] = 0x02;␊ |
558 | ␉␉␉resource_template_register_fixedhw[18] = 0x01;␊ |
559 | ␊ |
560 | ␉␉␉resource_template_register_fixedhw[11] = 0x00; // C1␊ |
561 | ␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
562 | ␉␉␉aml_add_byte(tmpl, 0x01);␉␉// C1␊ |
563 | ␉␉␉aml_add_word(tmpl, 0x0001);␉␉// Latency␊ |
564 | ␉␉␉aml_add_dword(tmpl, 0x000003e8);␉// Power␊ |
565 | ␊ |
566 | ␉␉␉resource_template_register_fixedhw[18] = 0x03;␊ |
567 | ␊ |
568 | ␉␉␉if (c2_enabled) // C2␊ |
569 | ␉␉␉{␊ |
570 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
571 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x10; // C2␊ |
572 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
573 | ␉␉␉␉aml_add_byte(tmpl, 0x02);␉␉// C2␊ |
574 | ␉␉␉␉aml_add_word(tmpl, 0x0040);␉␉// Latency␊ |
575 | ␉␉␉␉aml_add_dword(tmpl, 0x000001f4);␉// Power␊ |
576 | ␉␉␉}␊ |
577 | ␊ |
578 | ␉␉␉if (c4_enabled) // C4␊ |
579 | ␉␉␉{␊ |
580 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
581 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x30; // C4␊ |
582 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
583 | ␉␉␉␉aml_add_byte(tmpl, 0x04);␉␉// C4␊ |
584 | ␉␉␉␉aml_add_word(tmpl, 0x0080);␉␉// Latency␊ |
585 | ␉␉␉␉aml_add_dword(tmpl, 0x000000C8);␉// Power␊ |
586 | ␉␉␉}␊ |
587 | ␉␉␉else if (c3_enabled)␊ |
588 | ␉␉␉{␊ |
589 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
590 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x20; // C3␊ |
591 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
592 | ␉␉␉␉aml_add_byte(tmpl, 0x03);␉␉// C3␊ |
593 | ␉␉␉␉aml_add_word(tmpl, 0x0043);␉␉// Latency␊ |
594 | ␉␉␉␉aml_add_dword(tmpl, 0x000001F4);␉// Power␊ |
595 | ␉␉␉}␊ |
596 | ␉␉␉if (c6_enabled) // C6␊ |
597 | ␉␉␉{␊ |
598 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
599 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x20; // C6␊ |
600 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
601 | ␉␉␉␉aml_add_byte(tmpl, 0x06);␉␉␉// C6␊ |
602 | ␉␉␉␉aml_add_word(tmpl, 0x0046);␉␉␉// Latency as in MacPro6,1␊ |
603 | ␉␉␉␉aml_add_dword(tmpl, 0x0000015E);␉// Power␊ |
604 | ␉␉␉}␊ |
605 | ␉␉␉if (c7_enabled) // C7␊ |
606 | ␉␉␉{␊ |
607 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
608 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x30; // C4 or C7␊ |
609 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
610 | ␉␉␉␉aml_add_byte(tmpl, 0x07);␉␉␉// C7␊ |
611 | ␉␉␉␉aml_add_word(tmpl, 0xF5);␉␉␉// Latency as in iMac14,1␊ |
612 | ␉␉␉␉aml_add_dword(tmpl, 0xC8);␉// Power␊ |
613 | ␉␉␉}␊ |
614 | ␉␉}␊ |
615 | ␊ |
616 | ␉␉// Aliaces␊ |
617 | ␉␉int i;␊ |
618 | ␉␉for (i = 0; i < acpi_cpu_count; i++)␊ |
619 | ␉␉{␊ |
620 | ␉␉␉char name[9];␊ |
621 | ␉␉␉sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);␊ |
622 | ␊ |
623 | ␉␉␉scop = aml_add_scope(root, name);␊ |
624 | ␉␉␉aml_add_alias(scop, "CST_", "_CST");␊ |
625 | ␉␉}␊ |
626 | ␊ |
627 | ␉␉aml_calculate_size(root);␊ |
628 | ␊ |
629 | ␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
630 | ␊ |
631 | ␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
632 | ␊ |
633 | ␉␉ssdt->Length = root->Size;␊ |
634 | ␉␉ssdt->Checksum = 0;␊ |
635 | ␉␉ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);␊ |
636 | ␊ |
637 | ␉␉aml_destroy_node(root);␊ |
638 | ␊ |
639 | ␉␉// dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);␊ |
640 | ␊ |
641 | ␉␉DBG("\tSSDT with CPU C-States generated successfully\n");␊ |
642 | ␊ |
643 | ␉␉return ssdt;␊ |
644 | ␉}␊ |
645 | ␉else␊ |
646 | ␉{␊ |
647 | ␉␉DBG("\tACPI CPUs not found: C-States not generated !!!\n");␊ |
648 | ␉}␊ |
649 | ␊ |
650 | ␉verbose("\n");␊ |
651 | ␊ |
652 | ␉return NULL;␊ |
653 | }␊ |
654 |