Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/ACPICodec/acpi_codec.c

  • Property svn:executable set to *
1/*
2 * Copyright 2008 mackerintel
3 */
4
5/*
6 Copyright (c) 2010, Intel Corporation
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11
12 * Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 * Neither the name of Intel Corporation nor the names of its contributors
18 may be used to endorse or promote products derived from this software
19 without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 2011 cparm <armelcadetpetit@gmail.com>. All rights reserved.
35 *
36 */
37
38#include "libsaio.h"
39#include "boot.h"
40#include "bootstruct.h"
41#include "acpi.h"
42#include "acpidecode.h"
43#include "acpicode.h"
44#include "efi_tables.h"
45#include "fake_efi.h"
46#include "acpi_codec.h"
47#include "platform.h"
48#include "cpu.h"
49#include "xml.h"
50#include "pci_root.h"
51#include "sl.h"
52#include "convert.h"
53
54U64 rsd_p;
55ACPI_TABLES acpi_tables;
56U32 uuid32;
57U32 Model32;
58bool checkOem = false;
59
60#ifndef DEBUG_ACPI
61#define DEBUG_ACPI 0
62#endif
63
64#if DEBUG_ACPI==2
65#define DBG(x...) {printf(x); sleep(1);}
66#elif DEBUG_ACPI==1
67#define DBG(x...) printf(x)
68#else
69#define DBG(x...)
70#endif
71
72#define OLD_SSDT 0
73#define BETA 0
74#define BUILD_ACPI_TSS 0
75#define pstate_power_support 1
76
77#if BETA
78#ifdef pstate_power_support
79#undef pstate_power_support
80#endif
81#define pstate_power_support 1
82#endif
83
84extern EFI_STATUS addConfigurationTable();
85
86extern EFI_GUID gEfiAcpiTableGuid;
87extern EFI_GUID gEfiAcpi20TableGuid;
88
89#if DEBUG_ACPI
90static void print_nameseg(U32 i);
91#endif
92
93static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex );
94static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature );
95static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved );
96static void sanitize_new_table_list(U32 *new_table_list );
97static void move_table_list_to_kmem(U32 *new_table_list );
98static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp );
99static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt);
100static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt);
101static void MakeAcpiSgn(void);
102static void *loadACPITable(U32 *new_table_list, char *dirspec, char *filename );
103static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer);
104static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length);
105static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list);
106static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list);
107static ACPI_TABLE_FADT * patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT);
108
109
110#define IA32_MISC_ENABLES 0x01A0
111#define MSR_TURBO_POWER_CURRENT_LIMIT 0x1AC
112#define MSR_PKG_CST_CONFIG_CONTROL 0x00E2
113#define MSR_RAPL_POWER_UNIT 0x606
114#define MSR_PKG_RAPL_POWER_LIMIT 0x610
115static U32 turbo_enabled = 0;
116static U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 NB_CPU);
117static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info);
118static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates);
119static bool is_sandybridge(void);
120static bool is_jaketown(void);
121static U32 encode_pstate(U32 ratio);
122static void collect_cpu_info(CPU_DETAILS * cpu);
123#ifndef BETA
124//static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu);
125#endif
126static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase);
127static U32 BuildPstateInfo(CPU_DETAILS * cpu);
128static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates );
129static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath);
130static void * buildPDC(void * current);
131static void * buildOSC(void * current);
132static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates);
133static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination);
134static void * buildPPC(void * current);
135static void * buildPCT(void * current);
136static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate);
137static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates);
138static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates);
139#if BUILD_ACPI_CSD
140static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates);
141#endif
142#if BUILD_ACPI_TSS
143static U32 BuildTstateInfo(CPU_DETAILS * cpu);
144static void * buildTPC(void * current);
145static void * buildPTC(void * current);
146static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates);
147static void * buildTSD(void * current, U32 domain, U32 cpusInDomain);
148#endif
149#if pstate_power_support
150static U64 mulU64byU64(U64 a, U64 b, U64 * high);
151static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP);
152#endif
153#if BUILD_ACPI_TSS || pstate_power_support
154static U64 divU64byU64(U64 n, U64 d, U64 * rem);
155static U32 compute_tdp(CPU_DETAILS * cpu);
156#endif
157static bool is_sandybridge(void);
158static bool is_jaketown(void);
159static U32 get_bclk(void);
160//static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate);
161//static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit);
162
163#if UNUSED
164static ACPI_TABLE_FACS* generate_facs(bool updatefacs );
165#endif
166
167#define MAX_NON_SSDT_TABLE 15
168#define MAX_SSDT_TABLE 15 // 15 additional SSDT tables
169#define MAX_ACPI_TABLE MAX_NON_SSDT_TABLE + MAX_SSDT_TABLE
170
171// Security space for SSDT , FACP & MADT table generation,
172// the size can be increased
173// note: the table will not placed in the reserved space if the 'normal' space is not full
174#define RESERVED_AERA 3
175
176#define ACPI_TABLE_LIST_FULL MAX_ACPI_TABLE + RESERVED_AERA + 1
177
178#define ACPI_TABLE_LIST_FULL_NON_RESERVED MAX_ACPI_TABLE + 1
179
180//#define ULONG_MAX_32 4294967295UL
181
182#define __RES(s, u)\
183inline unsigned u\
184resolve_##s(unsigned u defaultentry, char *str, int base) \
185{\
186unsigned u entry = defaultentry;\
187if (str && (strcmp(str,"Default") != 0)) {\
188entry = strtoul((const char *)str, NULL,base);\
189}\
190return entry;\
191}
192
193__RES(pss, long)
194__RES(cst, int)
195
196
197static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex )
198{
199ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
200U8 index ;
201*retIndex = 0;
202
203for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
204{
205if (*(U32 *) (table_array[index]->Signature) == Signature)
206{
207*retIndex = index;
208return table_array[index] ;
209}
210}
211return (void*)0ul;
212}
213
214static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature )
215{
216ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
217U8 index ;
218U8 InstalledTables = 0;
219
220for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
221{
222if (*(U32 *) (table_array[index]->Signature) == Signature)
223{
224InstalledTables++ ;
225}
226}
227return InstalledTables;
228}
229
230static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved )
231{
232U8 index ;
233
234U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE;
235
236for (index = 0; index < maximum; index++)
237{
238if (new_table_list[index] == 0ul)
239{
240return index ;
241}
242}
243return (reserved == true)? ACPI_TABLE_LIST_FULL : ACPI_TABLE_LIST_FULL_NON_RESERVED;
244}
245
246/* cparm : This time we check it by the acpi signature */
247static void sanitize_new_table_list(U32 *new_table_list )
248{
249ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
250U8 index ;
251
252for (index = 0; index < MAX_ACPI_TABLE; index++)
253{
254U32 current_sig = *(U32 *) (table_array[index]->Signature);
255
256if ((current_sig == NAMESEG(ACPI_SIG_FACS) /* not supported */ )
257|| (current_sig == NAMESEG(ACPI_SIG_XSDT))
258|| (current_sig == NAMESEG(ACPI_SIG_RSDT)) || (*(volatile U64 *)table_array[index] == NAMESEG64(ACPI_SIG_RSDP)) )
259{
260
261void *buf = (void*)new_table_list[index];
262free(buf);
263new_table_list[index] = 0ul ;
264}
265}
266}
267
268/* cparm : move all tables to kernel memory */
269static void move_table_list_to_kmem(U32 *new_table_list )
270{
271ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
272U8 index ;
273
274for (index = 0; index < MAX_ACPI_TABLE; index++)
275{
276if (new_table_list[index] != 0ul)
277{
278
279U32 current_sig = *(U32 *) (table_array[index]->Signature);
280if ((current_sig != NAMESEG(ACPI_SIG_FACS) /* not supported */ )
281&& (current_sig != NAMESEG(ACPI_SIG_XSDT))
282&& (current_sig != NAMESEG(ACPI_SIG_RSDT)) && (*(volatile U64 *)table_array[index] != NAMESEG64(ACPI_SIG_RSDP))
283&& (GetChecksum(table_array[index], table_array[index]->Length) == 0))
284{
285
286void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length);
287if (!tableAddr) {
288printf("Unable to allocate kernel memory for aml file ");
289
290void *buf = (void*)new_table_list[index];
291free(buf);
292new_table_list[index] = 0ul ;
293continue;
294}
295bcopy(table_array[index], tableAddr, table_array[index]->Length);
296new_table_list[index] = 0ul ;
297new_table_list[index] = (U32)tableAddr ;
298
299}
300else
301{
302
303void *buf = (void*)new_table_list[index];
304free(buf);
305new_table_list[index] = 0ul ;
306}
307}
308}
309}
310
311static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp )
312{
313
314ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP));
315
316if (rsdp_conv) {
317bzero(rsdp_conv, sizeof(ACPI_TABLE_RSDP));
318memcpy(rsdp_conv, rsdp, ACPI_RSDP_REV0_SIZE);
319
320/* Add/change fields */
321rsdp_conv->Revision = 2; /* ACPI version 3 */
322rsdp_conv->Length = sizeof(ACPI_TABLE_RSDP);
323
324/* Correct checksums */
325setRsdpchecksum(rsdp_conv);
326setRsdpXchecksum(rsdp_conv);
327}
328
329 return (rsdp_conv) ? rsdp_conv : (void*)0ul ;
330}
331
332static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt)
333{
334 U32 index;
335 U32 num_tables;
336
337DBG("Attempting to generate RSDT from XSDT \n");
338
339 num_tables= get_num_tables64(xsdt);
340
341 ACPI_TABLE_RSDT * rsdt_conv=(ACPI_TABLE_RSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
342if (!rsdt_conv)
343{
344printf("Unable to allocate kernel memory for rsdt conv\n");
345return (void*)0ul;
346}
347
348
349bzero(rsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
350 memcpy(&rsdt_conv->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
351
352 rsdt_conv->Header.Signature[0] = 'R';
353 rsdt_conv->Header.Signature[1] = 'S';
354 rsdt_conv->Header.Signature[2] = 'D';
355 rsdt_conv->Header.Signature[3] = 'T';
356 rsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 4);
357
358for (index=0;index<num_tables;index++)
359 {
360U64 ptr = xsdt->TableOffsetEntry[index];
361
362{
363if (ptr > ULONG_MAX)
364{
365#if DEBUG_ACPI
366printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
367#endif
368continue;
369}
370#if DEBUG_ACPI
371printf("* Processing : ");
372print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
373printf("\n");
374#endif
375bool unsafe = false;
376getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
377
378if (!unsafe)
379{
380if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
381((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
382{
383#if DEBUG_ACPI
384printf("Warning : Invalide checksum, ignored !!!\n",index);
385#endif
386continue;
387}
388}
389
390}
391
392{
393if ((*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == NAMESEG(ACPI_SIG_FADT)))
394{
395ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)ptr);
396
397ACPI_TABLE_FADT *fadt_conv = (void*)0ul;
398
399if (fadt->Header.Revision > 1)
400{
401U8 buffer[0x74];
402DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision);
403fadt_conv=(ACPI_TABLE_FADT *)buffer;
404memcpy(fadt_conv, fadt, 0x74);
405fadt_conv->Header.Length = 0x74;
406fadt_conv->Header.Revision = 0x01;
407SetChecksum(&fadt_conv->Header);
408}
409else
410{
411fadt_conv = fadt;
412}
413
414ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false);
415if (fadt_mod == (void*)0ul)
416{
417printf("Error: Failed to patch FADT Table, trying wiht the original fadt pointer\n");
418fadt_mod = fadt;
419}
420
421rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod);
422#if DEBUG_ACPI
423print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
424printf(" table converted and added succesfully\n");
425#endif
426continue;
427}
428}
429
430{
431rsdt_conv->TableOffsetEntry[index] = (U32)ptr;
432#if DEBUG_ACPI
433print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
434printf(" table converted and added succesfully\n");
435#endif
436}
437
438 }
439 DBG("RSDT_CONV : Original checksum %d\n", rsdt_conv->Header.Checksum);
440 SetChecksum(&rsdt_conv->Header);
441 DBG("New checksum %d\n", rsdt_conv->Header.Checksum);
442
443 return rsdt_conv;
444}
445
446static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt)
447{
448U32 index;
449 U32 num_tables;
450
451DBG("Attempting to generate XSDT from RSDT \n");
452
453 num_tables= get_num_tables(rsdt);
454
455 ACPI_TABLE_XSDT * xsdt_conv=(ACPI_TABLE_XSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
456
457if (!xsdt_conv) {
458printf("Unable to allocate kernel memory for xsdt conv\n");
459return (void*)0ul;
460}
461
462bzero(xsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
463 memcpy(&xsdt_conv->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
464
465 xsdt_conv->Header.Signature[0] = 'X';
466 xsdt_conv->Header.Signature[1] = 'S';
467 xsdt_conv->Header.Signature[2] = 'D';
468 xsdt_conv->Header.Signature[3] = 'T';
469 xsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 8);
470
471ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
472
473 for (index=0;index<num_tables;index++)
474 {
475{
476#if DEBUG_ACPI
477printf("* Processing : ");
478print_nameseg(*(U32*) (table_array[index]->Signature));
479printf("\n");
480#endif
481bool unsafe = false;
482getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
483
484if (!unsafe)
485{
486if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
487{
488#if DEBUG_ACPI
489printf("Warning : Invalide checksum, ignored !!!\n",index);
490#endif
491continue;
492}
493}
494
495}
496
497{
498if ((*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT)))
499{
500ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]);
501ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true);
502if (fadt_mod == (void*)0ul)
503{
504printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n");
505fadt_mod = FacpPointer;
506}
507xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod));
508
509continue;
510}
511}
512
513xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index]));
514 }
515 DBG("XSDT_CONV : Original checksum %d\n", xsdt_conv->Header.Checksum);
516 SetChecksum(&xsdt_conv->Header);
517 DBG("New checksum %d\n", xsdt_conv->Header.Checksum);
518
519 return xsdt_conv;
520}
521
522static void MakeAcpiSgn(void)
523{
524
525char * DefaultplatformName = NULL;
526Model32 = 0;
527
528if (DefaultplatformName = readDefaultPlatformName())
529{
530Model32 = OSSwapHostToBigInt32(adler32( (unsigned char *) DefaultplatformName, strlen(DefaultplatformName)));
531}
532
533uuid32 = 0;
534
535const char *uuidStr = getStringFromUUID(Platform->sysid);
536
537if (strlen(uuidStr))
538{
539uuid32 = OSSwapHostToBigInt32(adler32( (unsigned char *) uuidStr, UUID_STR_LEN ));
540}
541
542}
543
544static void *loadACPITable(U32 *new_table_list, char *dirspec, char *filename )
545{
546int fd = -1;
547char acpi_file[512];
548
549DBG("Searching for %s file ...\n", filename);
550// Check booting partition
551
552sprintf(acpi_file, "%s%s",dirspec, filename);
553
554HFSLoadVerbose = 0;
555fd=open(acpi_file);
556
557if (fd<0)
558{
559DBG("Couldn't open ACPI Table: %s\n", acpi_file);
560return (void *)0ul ;
561}
562
563void *tableAddr=(void*)malloc(file_size (fd));
564
565if (tableAddr)
566{
567if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
568{
569printf("Couldn't read table %s\n",acpi_file);
570free (tableAddr);
571close (fd);
572return (void *)0ul ;
573}
574
575close (fd);
576
577ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr;
578
579if (*(U32*)(header->Signature) != NAMESEG("SSDT"))
580{
581U8 dummy = 0;
582if (get_new_table_in_list(new_table_list, *(U32*)(header->Signature), &dummy))
583{
584#if DEBUG_ACPI
585printf("Warning: A ");
586print_nameseg(*(U32*) (header->Signature));
587printf(" Aml file is already loaded and registred, file skipped !!\n");
588#endif
589free(tableAddr);
590return (void*)0ul;
591}
592}
593else
594{
595if (get_number_of_tables_in_list(new_table_list, NAMESEG("SSDT")) >= MAX_SSDT_TABLE)
596{
597DBG("Warning: Max number of SSDT aml files reached, file skipped !!\n");
598free(tableAddr);
599return (void*)0ul;
600}
601}
602
603
604if (checkOem == true)
605{
606if (header->OemRevision == Model32)
607{
608goto continue_loading;
609}
610
611if (header->OemRevision == uuid32)
612{
613goto continue_loading;
614}
615
616DBG("Bad signature aka Oem Revision (0x%08lx) for Aml file (%s), file skipped !!\n", header->OemRevision, acpi_file);
617DBG("uuid32 (0x%08lx) , model32 (0x%08lx)\n", uuid32, Model32);
618
619free(tableAddr);
620return (void*)0ul;
621}
622
623continue_loading:
624
625if (GetChecksum(header, header->Length) == 0)
626{
627DBG("Found valid AML file : %s ", filename);
628printf("[ %s ] read and stored at: %x", acpi_file, tableAddr);
629printf("\n");
630return tableAddr;
631}
632else
633{
634printf("Warning : Incorrect cheksum for the file : %s,", acpi_file);
635printf(" this file will be dropped.\n");
636free(tableAddr);
637return (void*)0ul;
638}
639}
640else
641{
642printf("Couldn't allocate memory for table %s\n", acpi_file);
643close (fd);
644}
645
646return (void *)0ul ;
647}
648
649static U32 pmbase;
650static short cpuNamespace;
651PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT];
652unsigned int cpu_map_count;
653int cpu_map_error;
654
655#if DEBUG_ACPI
656static void print_nameseg(U32 i)
657{
658 printf("%c%c%c%c",
659 (int)(i & 0x000000ff),
660 (int)((i & 0x0000ff00) >> 8),
661 (int)((i & 0x00ff0000) >> 16),
662 (int)(i >> 24));
663}
664#endif
665
666static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer)
667{
668 PROCESSOR_NUMBER_TO_NAMESEG *map = cpu_map;
669 U32 processor_namespace = 0;
670 U32 cpu;
671 U8 *current, *end;
672 ACPI_TABLE_HEADER *header;
673 struct acpi_namespace ns;
674
675if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul))
676return 1;
677else if (cpu_map_count > 0)
678return 0;
679
680 DBG("Attempting to autodetect CPU map from ACPI DSDT; wish me luck\n");
681
682 current = (U8 *) DsdtPointer;
683 current = decodeTableHeader(current, &header);
684 end = current - sizeof(*header) + header->Length;
685 ns.depth = 0;
686 acpi_processor_count = 0;
687//DBG("* DSDT debug start\n");
688 parse_acpi_termlist(&ns, current, end);
689//DBG("* DSDT debug end\n");
690
691 if (acpi_processor_count > CPU_MAP_LIMIT)
692{
693verbose("Too many processors: found %u processors\n", acpi_processor_count);
694 return (cpu_map_error = 1);
695}
696 if (acpi_processor_count == 0)
697{
698verbose( "Found no processors in ACPI\n");
699 return (cpu_map_error = 1);
700}
701 for (cpu = 0; cpu < acpi_processor_count; cpu++)
702{
703 U32 nameseg;
704 if (acpi_processors[cpu].pmbase)
705{
706 U32 cpu_pmbase = acpi_processors[cpu].pmbase - 0x10;
707 if (pmbase && cpu_pmbase != pmbase)
708{
709verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase);
710return (cpu_map_error = 1);
711}
712 pmbase = cpu_pmbase;
713 }
714 if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1)
715{
716verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth);
717return (cpu_map_error = 1);
718}
719 if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace)
720{
721verbose("Processor namespaces inconsistent\n");
722return (cpu_map_error = 1);
723}
724 processor_namespace = acpi_processors[cpu].ns.nameseg[0];
725 map->acpi_processor_number = acpi_processors[cpu].id;
726 map->seg_count = acpi_processors[cpu].ns.depth - 1;
727 for (nameseg = 0; nameseg < map->seg_count; nameseg++)
728 map->nameseg[nameseg] = acpi_processors[cpu].ns.nameseg[nameseg + 1];
729 map++;
730 }
731 if (!pmbase)
732{
733verbose("No pmbase found in ACPI\n");
734return (cpu_map_error = 1);
735}
736 if (processor_namespace == NAMESEG("_PR_"))
737 cpuNamespace = CPU_NAMESPACE_PR;
738 else if (processor_namespace == NAMESEG("_SB_"))
739 cpuNamespace = CPU_NAMESPACE_SB;
740 else
741{
742 verbose("Found processors in invalid namespace; not _PR_ or _SB_\n");
743return (cpu_map_error = 1);
744}
745 cpu_map_count = map - cpu_map;
746
747#if DEBUG_ACPI
748verbose("Found %d processors in ACPI, pmbase : 0x%x, cpu_map_count : %d, namespace : ",acpi_processor_count, pmbase, cpu_map_count );
749print_nameseg(processor_namespace);
750verbose("\n");
751 U32 i;
752 verbose("Found processors name : \n" );
753 for ( i = 0; i<cpu_map_count; i++)
754{
755U32 nseg = *(U32*)cpu_map[i].nameseg;
756 print_nameseg(nseg);
757verbose(" ");
758 }
759 verbose("\n");
760#endif
761
762// TODO: Save the cpu map into the device tree
763 return (cpu_map_error = 0);
764}
765
766static bool is_sandybridge(void)
767{
768 return Platform->CPU.Model == CPUID_MODEL_SANDYBRIDGE;
769}
770
771static bool is_jaketown(void)
772{
773 return Platform->CPU.Model == CPUID_MODEL_JAKETOWN;
774}
775
776static U32 get_bclk(void)
777{
778return (is_jaketown() || is_sandybridge()) ? 100 : 133;
779}
780/*
781//-----------------------------------------------------------------------------
782static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate)
783{
784U32 ratiorange = max-min;
785U32 numGaps = numStates-1-turboEnabled;
786U32 adjPstate = pstate-turboEnabled;
787return (pstate == 0) ? (max + turboEnabled) :
788(ratiorange == 0) ? max :
789max-(((adjPstate*ratiorange)+(numGaps/2))/numGaps);
790}
791//-----------------------------------------------------------------------------
792static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit)
793{
794U32 ratiorange, maxStates, numStates;
795
796ratiorange = max - min + 1;
797maxStates = ratiorange + (turboEnabled ? 1 : 0);
798numStates = (pssLimit < maxStates) ? pssLimit : maxStates;
799return (numStates < 2) ? 0 : numStates;
800}
801*/
802#if BUILD_ACPI_TSS || pstate_power_support
803static U64 divU64byU64(U64 n, U64 d, U64 * rem)
804{
805 U32 i;
806 U64 q = n;
807 U64 r = 0;
808
809 for (i = 0; i < 64; i++) {
810 r <<= 1;
811 r |= (q & (1ULL << 63)) >> 63;
812 q <<= 1;
813 if (r >= d) {
814 r -= d;
815 q |= 1;
816 }
817 }
818 if (rem)
819 *rem = r;
820 return q;
821}
822
823static U32 compute_tdp(CPU_DETAILS * cpu)
824{
825
826 {
827 if (is_jaketown() || is_sandybridge())
828 {
829 U64 power_limit_1 = cpu->package_power_limit & ((1ULL << 15) - 1);
830 U64 power_unit = cpu->package_power_sku_unit & ((1ULL << 4) - 1);
831 U64 tdp = divU64byU64(power_limit_1, 1 << power_unit, NULL);
832 return (U32)tdp;
833 }
834 else
835 {
836 // tdp = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [14:0] / 8) Watts
837 return cpu->tdp_limit / 8;
838 }
839 }
840
841}
842#endif // BUILD_ACPI_TSS || pstate_power_support
843
844#if pstate_power_support
845static U64 mulU64byU64(U64 a, U64 b, U64 * high)
846{
847 U64 b_high = 0;
848 U64 r_high = 0, r_low = 0;
849 U64 bit;
850
851 for (bit = 1; bit; bit <<= 1) {
852 if (a & bit) {
853 if (r_low + b < r_low)
854 r_high++;
855 r_low += b;
856 r_high += b_high;
857 }
858 b_high <<= 1;
859 b_high |= (b & (1ULL << 63)) >> 63;
860 b <<= 1;
861 }
862
863 if (high)
864 *high = r_high;
865 return r_low;
866}
867
868static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP)
869{
870if (is_jaketown() || is_sandybridge())
871{
872U32 P1_Ratio = cpu->max_ratio_as_mfg;
873U64 M, pstate_power;
874
875// M = ((1.1 - ((P1_ratio - ratio) * 0.00625)) / 1.1) ^2
876// To prevent loss of precision compute M * 10^5 (preserves 5 decimal places)
877M = (P1_Ratio - ratio) * 625;
878M = (110000 - M);
879M = divU64byU64(M, 11, NULL);
880M = divU64byU64(mulU64byU64(M, M, NULL), 1000, NULL);
881
882// pstate_power = ((ratio/p1_ratio) * M * TDP)
883// Divide the final answer by 10^5 to remove the precision factor
884pstate_power = mulU64byU64(ratio, M, NULL);
885pstate_power = mulU64byU64(pstate_power, TDP, NULL);
886pstate_power = divU64byU64(pstate_power, P1_Ratio, NULL);
887pstate_power = divU64byU64(pstate_power, 100000, NULL);
888return (U32)pstate_power; // in Watts
889}
890else
891{
892// pstate_power[ratio] = (ratio/P1_ratio)^3 * Core_TDP + Uncore_TDP
893
894// Core_TDP = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [30:16] / 8) Watts
895U32 Core_TDP = cpu->tdc_limit / 8;
896
897// Uncore_TDP = TDP - Core_TDP
898U32 Uncore_TDP = TDP - Core_TDP;
899
900// max_ratio_as_mfg = P1_Ratio derived from Brand String returned by CPUID instruction
901U32 P1_Ratio = cpu->max_ratio_as_mfg;
902
903#define PRECISION_FACTOR (U32) 30
904#define PRECISION_FACTOR_CUBED (U32) (PRECISION_FACTOR * PRECISION_FACTOR * PRECISION_FACTOR)
905
906U32 ratio_factor = (ratio * PRECISION_FACTOR)/P1_Ratio;
907return ((ratio_factor * ratio_factor * ratio_factor * Core_TDP) / PRECISION_FACTOR_CUBED) + Uncore_TDP;
908}
909}
910#endif // pstate_power_support
911
912static U32 encode_pstate(U32 ratio)
913{
914if (is_jaketown() || is_sandybridge())
915return ratio << 8;
916return ratio;
917}
918
919//-----------------------------------------------------------------------------
920void GetMaxRatio(U32 * max_non_turbo_ratio)
921{
922U32 index;
923U32 max_ratio=0;
924U32 frequency=0;
925 U32 multiplier = 0;
926// Verify CPUID brand string function is supported
927if (Platform->CPU.cpuid_max_ext < 80000004)
928{
929*max_non_turbo_ratio = max_ratio;
930return;
931}
932
933 // -2 to prevent buffer overrun because looking for y in yHz, so z is +2 from y
934 for (index=0; index<48-2; index++) {
935 // format is either “x.xxyHz” or “xxxxyHz”, where y=M,G,T and x is digits
936 // Search brand string for “yHz” where y is M, G, or T
937 // Set multiplier so frequency is in MHz
938 if ( Platform->CPU.BrandString[index+1] == 'H' && Platform->CPU.BrandString[index+2] == 'z')
939 {
940 if (Platform->CPU.BrandString[index] == 'M')
941 multiplier = 1;
942 else if (Platform->CPU.BrandString[index] == 'G')
943 multiplier = 1000;
944 else if (Platform->CPU.BrandString[index] == 'T')
945 multiplier = 1000000;
946 }
947 if (multiplier > 0 && index >= 4 /* who can i call that, buffer underflow :-) ??*/)
948 {
949 // Copy 7 characters (length of “x.xxyHz”)
950 // index is at position of y in “x.xxyHz”
951
952 // Compute frequency (in MHz) from brand string
953 if (Platform->CPU.BrandString[index-3] == '.')
954 { // If format is “x.xx”
955 if (isdigit(Platform->CPU.BrandString[index-4]) && isdigit(Platform->CPU.BrandString[index-2]) &&
956 isdigit(Platform->CPU.BrandString[index-1]))
957 {
958 frequency = (U32)(Platform->CPU.BrandString[index-4] - '0') * multiplier;
959 frequency += (U32)(Platform->CPU.BrandString[index-2] - '0') * (multiplier / 10);
960 frequency += (U32)(Platform->CPU.BrandString[index-1] - '0') * (multiplier / 100);
961 }
962 }
963 else
964 { // If format is xxxx
965 if (isdigit(Platform->CPU.BrandString[index-4]) && isdigit(Platform->CPU.BrandString[index-3]) &&
966 isdigit(Platform->CPU.BrandString[index-2]) && isdigit(Platform->CPU.BrandString[index-1]))
967 {
968 frequency = (U32)(Platform->CPU.BrandString[index-4] - '0') * 1000;
969 frequency += (U32)(Platform->CPU.BrandString[index-3] - '0') * 100;
970 frequency += (U32)(Platform->CPU.BrandString[index-2] - '0') * 10;
971 frequency += (U32)(Platform->CPU.BrandString[index-1] - '0');
972 frequency *= multiplier;
973 }
974
975 }
976
977 max_ratio = frequency / get_bclk();
978 break;
979 }
980 }
981
982// Return non-zero Max Non-Turbo Ratio obtained from CPUID brand string
983// or return 0 indicating Max Non-Turbo Ratio not available
984*max_non_turbo_ratio = max_ratio;
985}
986
987//-----------------------------------------------------------------------------
988static void collect_cpu_info(CPU_DETAILS * cpu)
989{
990
991#if BUILD_ACPI_TSS || pstate_power_support
992 cpu->turbo_available = Platform->CPU.dynamic_acceleration;
993
994{
995U32 temp32 = 0;
996U64 temp64= 0;
997int tdp;
998if (getIntForKey("TDP", &tdp, &bootInfo->bootConfig))
999{
1000temp32 = (U32) (tdp*8) ;
1001
1002int tdc;
1003if (getIntForKey("TDC", &tdc, &bootInfo->bootConfig))
1004{
1005temp32 = (U32) (temp32) | tdc<<16 ;
1006
1007}
1008else if (tdp)
1009{
1010temp32 = (U32) (temp32) | ((tdp)*8)<<16 ;
1011}
1012
1013}
1014else if (!is_sandybridge() && !is_jaketown())
1015{
1016if (turbo_enabled && cpu->turbo_available)
1017{
1018temp64 = rdmsr64(MSR_TURBO_POWER_CURRENT_LIMIT);
1019temp32 = (U32)temp64;
1020}
1021else
1022{
1023// Unfortunately, Intel don't provide a better method for non turbo processors
1024// and it will give a TDP of 95w (for ex. mine is 65w) , to fix this issue,
1025// you can set this value by simply adding the option TDP = XX (XX is an integer)
1026// in your boot.plist
1027temp32 = (U32)0x02a802f8;
1028}
1029
1030}
1031if (temp32) {
1032cpu->tdp_limit = ( temp32 & 0x7fff );
1033cpu->tdc_limit = ( (temp32 >> 16) & 0x7fff );
1034}
1035}
1036
1037#endif
1038
1039switch (Platform->CPU.Family)
1040{
1041case 0x06:
1042{
1043switch (Platform->CPU.Model)
1044{
1045case CPUID_MODEL_DOTHAN:
1046case CPUID_MODEL_YONAH: // Yonah
1047case CPUID_MODEL_MEROM: // Merom
1048case CPUID_MODEL_PENRYN: // Penryn
1049case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1050{
1051
1052cpu->core_c1_supported = ((Platform->CPU.sub_Cstates >> 4) & 0xf) ? 1 : 0;
1053cpu->core_c4_supported = ((Platform->CPU.sub_Cstates >> 16) & 0xf) ? 1 : 0;
1054
1055if (Platform->CPU.Model == CPUID_MODEL_ATOM)
1056{
1057cpu->core_c2_supported = cpu->core_c3_supported = ((Platform->CPU.sub_Cstates >> 8) & 0xf) ? 1 : 0;
1058cpu->core_c6_supported = ((Platform->CPU.sub_Cstates >> 12) & 0xf) ? 1 : 0;
1059
1060}
1061else
1062{
1063cpu->core_c3_supported = ((Platform->CPU.sub_Cstates >> 12) & 0xf) ? 1 : 0;
1064cpu->core_c2_supported = ((Platform->CPU.sub_Cstates >> 8) & 0xf) ? 1 : 0;
1065cpu->core_c6_supported = 0;
1066
1067}
1068
1069cpu->core_c7_supported = 0;
1070
1071#if BETA
1072GetMaxRatio(&cpu->max_ratio_as_mfg);
1073U64 msr = rdmsr64(MSR_IA32_PERF_STATUS);
1074U16 idlo = (msr >> 48) & 0xffff;
1075U16 idhi = (msr >> 32) & 0xffff;
1076cpu->min_ratio = (U32) (idlo >> 8) & 0xff;
1077cpu->max_ratio_as_cfg = (U32) (idhi >> 8) & 0xff;
1078
1079#else
1080if (Platform->CPU.MaxCoef)
1081{
1082if (Platform->CPU.MaxDiv)
1083{
1084cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) (Platform->CPU.MaxCoef * 10) + 5;
1085}
1086else
1087{
1088cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) Platform->CPU.MaxCoef * 10;
1089}
1090}
1091#endif
1092
1093break;
1094}
1095case CPUID_MODEL_FIELDS:
1096case CPUID_MODEL_DALES:
1097case CPUID_MODEL_DALES_32NM:
1098case CPUID_MODEL_NEHALEM:
1099case CPUID_MODEL_NEHALEM_EX:
1100case CPUID_MODEL_WESTMERE:
1101case CPUID_MODEL_WESTMERE_EX:
1102case CPUID_MODEL_SANDYBRIDGE:
1103case CPUID_MODEL_JAKETOWN:
1104{
1105
1106cpu->core_c1_supported = ((Platform->CPU.sub_Cstates >> 4) & 0xf) ? 1 : 0;
1107cpu->core_c3_supported = ((Platform->CPU.sub_Cstates >> 8) & 0xf) ? 1 : 0;
1108cpu->core_c6_supported = ((Platform->CPU.sub_Cstates >> 12) & 0xf) ? 1 : 0;
1109cpu->core_c7_supported = ((Platform->CPU.sub_Cstates >> 16) & 0xf) ? 1 : 0;
1110cpu->core_c2_supported = 0;
1111cpu->core_c4_supported = 0;
1112
1113GetMaxRatio(&cpu->max_ratio_as_mfg);
1114 U64 platform_info = rdmsr64(MSR_PLATFORM_INFO);
1115 cpu->max_ratio_as_cfg = (U32) ((U32)platform_info >> 8) & 0xff;
1116cpu->min_ratio = (U32) ((platform_info >> 40) & 0xff);
1117
1118if (is_sandybridge() || is_jaketown())
1119{
1120cpu->package_power_limit = rdmsr64(MSR_PKG_RAPL_POWER_LIMIT);
1121cpu->package_power_sku_unit = rdmsr64(MSR_RAPL_POWER_UNIT);
1122}
1123break;
1124}
1125default:
1126verbose ("Unsupported CPU\n");
1127return /*(0)*/;
1128break;
1129}
1130}
1131default:
1132break;
1133}
1134
1135cpu->mwait_supported = (Platform->CPU.extensions & (1UL << 0)) ? 1 : 0;
1136
1137 cpu->invariant_apic_timer_flag = Platform->CPU.invariant_APIC_timer;
1138
1139#if DEBUG_ACPI
1140printf("CPU INFO : \n");
1141#if BETA
1142printf("min_ratio : %d\n", cpu->min_ratio);
1143#endif
1144printf("max_ratio_as_cfg : %d\n", cpu->max_ratio_as_cfg);
1145printf("max_ratio_as_mfg : %d\n", cpu->max_ratio_as_mfg);
1146
1147printf("turbo_available : %d\n",cpu->turbo_available);
1148
1149printf("core_c1_supported : %d\n",cpu->core_c1_supported);
1150printf("core_c2_supported : %d\n",cpu->core_c1_supported);
1151printf("core_c3_supported : %d\n",cpu->core_c3_supported);
1152printf("core_c6_supported : %d\n",cpu->core_c6_supported);
1153printf("core_c7_supported : %d\n",cpu->core_c7_supported);
1154printf("mwait_supported : %d\n",cpu->mwait_supported);
1155
1156#if BUILD_ACPI_TSS || pstate_power_support
1157if (is_sandybridge() || is_jaketown())
1158{
1159
1160printf("package_power_limit : %d\n",cpu->package_power_limit);
1161printf("package_power_sku_unit : %d\n",cpu->package_power_sku_unit);
1162
1163}
1164#endif
1165
1166DBG("invariant_apic_timer_flag : %d\n",cpu->invariant_apic_timer_flag);
1167
1168
1169#endif
1170}
1171
1172#if BETA
1173//-----------------------------------------------------------------------------
1174static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1175{
1176// Build P-state table info based on verified options
1177
1178// Compute the number of p-states based on the ratio range
1179cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1180
1181if (!cpu->pkg_pstates.num_pstates)
1182{
1183return (0);
1184}
1185
1186// Compute pstate data
1187{
1188U32 TDP = compute_tdp(cpu);
1189
1190U32 index;
1191for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1192{
1193PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1194
1195// Set ratio
1196pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1197
1198// Compute frequency based on ratio
1199if ((index != 0) || (cpu->turbo_available == 0))
1200pstate->frequency = pstate->ratio * get_bclk();
1201else
1202pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1203
1204// Compute power based on ratio and other data
1205if (pstate->ratio >= cpu->max_ratio_as_mfg)
1206// Use max power in mW
1207pstate->power = TDP * 1000;
1208else
1209{
1210pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1211
1212// Convert to mW
1213pstate->power*= 1000;
1214}
1215}
1216}
1217
1218return (1);
1219}
1220#else
1221/*
1222//-----------------------------------------------------------------------------
1223static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu)
1224{
1225// Build P-state table info based on verified options
1226
1227// Compute the number of p-states based on the ratio range
1228cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1229
1230if (!cpu->pkg_pstates.num_pstates)
1231{
1232return (0);
1233}
1234
1235// Compute pstate data
1236{
1237#ifdef pstate_power_support
1238U32 TDP = compute_tdp(cpu);
1239#endif
1240
1241U32 index;
1242for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1243{
1244PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1245
1246// Set ratio
1247pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1248
1249// Compute frequency based on ratio
1250if ((index != 0) || (cpu->turbo_available == 0))
1251pstate->frequency = pstate->ratio * get_bclk();
1252else
1253pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1254
1255#ifdef pstate_power_support
1256// Compute power based on ratio and other data
1257if (pstate->ratio >= cpu->max_ratio_as_mfg)
1258// Use max power in mW
1259pstate->power = TDP * 1000;
1260else
1261{
1262pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1263
1264// Convert to mW
1265pstate->power*= 1000;
1266}
1267#else
1268pstate->power = 0;
1269#endif
1270}
1271}
1272
1273return (1);
1274}
1275*/
1276//-----------------------------------------------------------------------------
1277static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1278{
1279
1280struct p_state p_states[32];
1281U8 p_states_count = 0;
1282{
1283#if UNUSED
1284struct p_state initial;
1285#endif
1286struct p_state maximum, minimum;
1287// Retrieving P-States, ported from code by superhai (c)
1288switch (Platform->CPU.Family)
1289{
1290case 0x06:
1291{
1292switch (Platform->CPU.Model)
1293{
1294case CPUID_MODEL_DOTHAN:
1295case CPUID_MODEL_YONAH: // Yonah
1296case CPUID_MODEL_MEROM: // Merom
1297case CPUID_MODEL_PENRYN: // Penryn
1298case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1299{
1300bool cpu_dynamic_fsb = false;
1301
1302if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
1303{
1304wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
1305delay(1);
1306cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
1307}
1308
1309bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
1310#if UNUSED
1311//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
1312#endif
1313maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
1314maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
1315
1316minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
1317minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
1318
1319if (minimum.FID == 0)
1320{
1321U64 msr;
1322U8 i;
1323// Probe for lowest fid
1324for (i = maximum.FID; i >= 0x6; i--)
1325{
1326msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1327wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
1328intel_waitforsts();
1329minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
1330delay(1);
1331}
1332
1333msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1334wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1335intel_waitforsts();
1336}
1337
1338if (minimum.VID == maximum.VID)
1339{
1340U64 msr;
1341U8 i;
1342// Probe for lowest vid
1343for (i = maximum.VID; i > 0xA; i--)
1344{
1345msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1346wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
1347intel_waitforsts();
1348minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
1349delay(1);
1350}
1351
1352msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1353wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1354intel_waitforsts();
1355}
1356
1357minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
1358
1359// Sanity check
1360if (maximum.CID < minimum.CID)
1361{
1362DBG("Insane FID values!");
1363p_states_count = 0;
1364}
1365else
1366{
1367// Finalize P-States
1368// Find how many P-States machine supports
1369p_states_count = maximum.CID - minimum.CID + 1;
1370
1371if (p_states_count > MAX_PSTATES) // was 32
1372p_states_count = MAX_PSTATES; // was 32
1373
1374U8 vidstep;
1375U8 i = 0, u, invalid = 0;
1376
1377vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
1378
1379for (u = 0; u < p_states_count; u++)
1380{
1381i = u - invalid;
1382
1383p_states[i].CID = maximum.CID - u;
1384p_states[i].FID = (p_states[i].CID >> 1);
1385
1386if (p_states[i].FID < 0x6)
1387{
1388if (cpu_dynamic_fsb)
1389p_states[i].FID = (p_states[i].FID << 1) | 0x80;
1390}
1391else if (cpu_noninteger_bus_ratio)
1392{
1393p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
1394}
1395
1396if (i && p_states[i].FID == p_states[i-1].FID)
1397invalid++;
1398
1399p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
1400
1401U32 multiplier = p_states[i].FID & 0x1f;// = 0x08
1402bool half = p_states[i].FID & 0x40;// = 0x01
1403bool dfsb = p_states[i].FID & 0x80;// = 0x00
1404U32 fsb = Platform->CPU.FSBFrequency / 1000000; // = 400
1405U32 halffsb = (fsb + 1) >> 1;// = 200
1406U32 frequency = (multiplier * fsb);// = 3200
1407
1408p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
1409}
1410
1411p_states_count -= invalid;
1412}
1413break;
1414}
1415case CPUID_MODEL_FIELDS:
1416case CPUID_MODEL_DALES:
1417case CPUID_MODEL_DALES_32NM:
1418case CPUID_MODEL_NEHALEM:
1419case CPUID_MODEL_NEHALEM_EX:
1420case CPUID_MODEL_WESTMERE:
1421case CPUID_MODEL_WESTMERE_EX:
1422case CPUID_MODEL_SANDYBRIDGE:
1423case CPUID_MODEL_JAKETOWN:
1424{
1425
1426maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
1427minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
1428
1429verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
1430
1431// Sanity check
1432if (maximum.Control < minimum.Control)
1433{
1434DBG("Insane control values!");
1435p_states_count = 0;
1436}
1437else
1438{
1439U8 i;
1440p_states_count = 0;
1441
1442for (i = maximum.Control; i >= minimum.Control; i--)
1443{
1444p_states[p_states_count].Control = i;
1445p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
1446p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i;
1447p_states_count++;
1448if (p_states_count >= MAX_PSTATES) { // was 32
1449
1450if (p_states_count > MAX_PSTATES) // was 32
1451p_states_count = MAX_PSTATES; // was 32
1452
1453break;
1454}
1455}
1456}
1457
1458/*
1459U32 sta = BuildCoreIPstateInfo(cpu);
1460if (sta)
1461{
1462DBG("_PSS PGK generated successfully\n");
1463return (1);
1464
1465}
1466else
1467{
1468verbose("CoreI _PSS Generation failed !!\n");
1469return (0);
1470}
1471*/
1472break;
1473}
1474default:
1475verbose ("Unsupported CPU: P-States will not be generated !!!\n");
1476return (0);
1477break;
1478}
1479}
1480default:
1481break;
1482}
1483}
1484
1485// Generating Pstate PKG
1486if (p_states_count)
1487{
1488U8 minPSratio = (p_states[p_states_count-1].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
1489U8 maxPSratio = (p_states[0].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
1490U8 cpu_ratio = 0;
1491
1492{
1493U8 cpu_div = Platform->CPU.CurrDiv;
1494
1495if (cpu_div)
1496cpu_ratio = (Platform->CPU.CurrCoef * 10) + 5;
1497else
1498cpu_ratio = Platform->CPU.CurrCoef * 10;
1499}
1500
1501
1502{
1503int user_max_ratio = 0;
1504getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->bootConfig);
1505if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio)
1506{
1507
1508U8 maxcurrdiv = 0, maxcurrcoef = (int)(user_max_ratio / 10);
1509
1510U8 maxdiv = user_max_ratio - (maxcurrcoef * 10);
1511if (maxdiv > 0)
1512maxcurrdiv = 1;
1513
1514if (maxcurrdiv)
1515cpu_ratio = (maxcurrcoef * 10) + 5;
1516else
1517cpu_ratio = maxcurrcoef * 10;
1518}
1519}
1520
1521{
1522int user_min_ratio = 0;
1523getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->bootConfig);
1524if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio)
1525{
1526
1527U8 mincurrdiv = 0, mincurrcoef = (int)(user_min_ratio / 10);
1528
1529U8 mindiv = user_min_ratio - (mincurrcoef * 10);
1530
1531if (mindiv > 0)
1532mincurrdiv = 1;
1533
1534if (mincurrdiv)
1535minPSratio = (mincurrcoef * 10) + 5;
1536else
1537minPSratio = mincurrcoef * 10;
1538
1539}
1540}
1541
1542
1543if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)maxPSratio = cpu_ratio;
1544
1545{
1546TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"P-States"));
1547int base = 16;
1548U8 expert = 0; /* Default: 0 , mean mixed mode
1549 * expert mode : 1 , mean add only p-states found in boot.plist
1550 */
1551
1552
1553{
1554if (personality)
1555{
1556char *tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Mode"));
1557
1558if (strcmp(tmpstr,"Expert") == 0)
1559{
1560p_states_count = XMLTagCount(personality) - 1 ; // - 1 = - ("Mode" tag)
1561expert = 1;
1562}
1563
1564
1565if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))))
1566{
1567
1568if (expert) p_states_count--; // -= ("Base" tag)
1569
1570int mybase = strtol(tmpstr, NULL, 10);
1571
1572if (mybase == 8 || mybase == 10 || mybase == 16 )
1573base = mybase;
1574}
1575}
1576
1577}
1578
1579{
1580U32 dropPSS = 0, Pstatus = 0;
1581char MatchStat[5];
1582#ifdef pstate_power_support
1583U32 TDP = compute_tdp(cpu);
1584#endif
1585U32 i;
1586for (i = 0; i < p_states_count; i++)
1587{
1588char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;
1589
1590if (personality)
1591{
1592sprintf(MatchStat, "%d",i);
1593TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
1594
1595if (match_Status)
1596{
1597
1598clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));
1599Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1600Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));
1601Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));
1602Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));
1603
1604
1605} else if (expert)
1606continue;
1607}
1608
1609unsigned long Frequency = 0x00000000;
1610
1611if (!expert || !personality) Frequency = p_states[i].Frequency;
1612
1613if (clk)
1614Frequency = strtoul((const char *)clk, NULL,base);
1615
1616if (!Frequency || Frequency > p_states[0].Frequency ) continue;
1617
1618U8 curr_ratio = (Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
1619
1620
1621 {
1622U8 fixed_ratio = (Frequency / (Platform->CPU.FSBFrequency / 1000000 ))*10;
1623U8 diff = curr_ratio - fixed_ratio ;
1624
1625if (diff)
1626{
1627if (diff < 5)
1628{
1629curr_ratio = fixed_ratio;
1630}
1631else
1632{
1633curr_ratio = fixed_ratio + 5;
1634}
1635}
1636
1637}
1638
1639if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
1640goto dropPstate;
1641
1642{
1643PSTATE * pstate = &cpu->pkg_pstates.pstate[Pstatus];
1644
1645pstate->ratio = curr_ratio;
1646
1647pstate->frequency = Frequency; // CoreFreq (in MHz).
1648
1649U32 power = 0x00000000;
1650#ifdef pstate_power_support
1651// Compute power based on ratio and other data
1652if (pstate->ratio >= cpu->max_ratio_as_mfg)
1653// Use max power in mW
1654power = TDP * 1000;
1655else
1656{
1657power = compute_pstate_power(cpu, pstate->ratio, TDP);
1658
1659// Convert to mW
1660power*= 1000;
1661}
1662#endif
1663pstate->power = resolve_pss(power, Pw, base); // Power (in milliWatts)
1664pstate->translatency = resolve_pss(0x0000000A, Lat1, base); // Transition Latency (in microseconds).
1665pstate->bmlatency = resolve_pss(0x0000000A, Lat2, base); // Bus Master Latency (in microseconds).
1666
1667{
1668U32 Control = 0 /*encode_pstate(curr_ratio)*/ ;
1669if (!expert || !personality) Control = p_states[i].Control;
1670pstate->control = resolve_pss(Control, Ctrl, base); // Control
1671}
1672
1673pstate->status = Pstatus+1; // Status
1674
1675DBG("state :: frequency :%d power: %d translatency: %d bmlatency: %d control: %d status: %d ratio :%d :: registred !! \n",pstate->frequency,pstate->power,
1676pstate->translatency,pstate->bmlatency,pstate->control,pstate->status,pstate->ratio );
1677}
1678
1679
1680Pstatus++;
1681continue;
1682
1683dropPstate:
1684DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
1685dropPSS++;
1686
1687
1688}
1689
1690if (Pstatus == 0)
1691{
1692verbose("No suitable P-states found, P-States will not be generated !!!\n");
1693return (0);
1694}
1695cpu->pkg_pstates.num_pstates = Pstatus;
1696}
1697}
1698}
1699else
1700{
1701verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
1702return (0);
1703}
1704
1705DBG("_PSS PGK generated successfully\n");
1706return (1);
1707}
1708#endif // BETA
1709
1710//-----------------------------------------------------------------------------
1711static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase)
1712{
1713{
1714TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));
1715
1716if (personality)
1717{
1718int base = 16;
1719
1720U32 entry_count = XMLTagCount(personality);
1721char *tmpstr =NULL;
1722
1723if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))))
1724{
1725
1726entry_count--; // -= ("Base" tag)
1727
1728int mybase = strtol(tmpstr, NULL, 10);
1729
1730if (mybase == 8 || mybase == 10 || mybase == 16 )
1731base = mybase;
1732}
1733
1734if (entry_count)
1735{
1736
1737cpu->pkg_io_cstates.num_cstates = 0;
1738cpu->pkg_mwait_cstates.num_cstates = 0;
1739U32 num_cstates = 0;
1740
1741{
1742U32 i;
1743char MatchStat[5];
1744
1745for (i = 0; i < 32 ; i++)
1746{
1747char *Lat = NULL, *Pw = NULL, *BWidth= NULL, *BOffset= NULL, *Address= NULL, *AccessSize= NULL, *index= NULL;
1748
1749sprintf(MatchStat, "C%d",i);
1750TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
1751if (match_Status)
1752{
1753Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1754Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
1755BWidth= XMLCastString(XMLGetProperty(match_Status, (const char*)"BitWidth"));
1756
1757BOffset = XMLCastString(XMLGetProperty(match_Status, (const char*)"BitOffset"));
1758Address = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
1759AccessSize = XMLCastString(XMLGetProperty(match_Status, (const char*)"AccessSize"));
1760index = XMLCastString(XMLGetProperty(match_Status, (const char*)"index"));
1761
1762if (Pw && Lat && BWidth && BOffset && Address && AccessSize && index)
1763{
1764U32 bw= strtoul((const char *)BWidth, NULL,base);
1765U32 boff= strtoul((const char *)BOffset, NULL,base);
1766U32 acs= strtoul((const char *)AccessSize, NULL,base);
1767U32 addr= strtoul((const char *)Address, NULL,base);
1768U32 idx= strtoul((const char *)index, NULL,base);
1769U32 lat= strtoul((const char *)Lat, NULL,base);
1770U32 pw= strtoul((const char *)Pw, NULL,base);
1771
1772ACPI_GENERIC_ADDRESS mwait_gas = {GAS_TYPE_FFH,bw,boff,acs,addr};
1773ACPI_GENERIC_ADDRESS io_gas = {(i == 1) ? GAS_TYPE_FFH : GAS_TYPE_SYSTEM_IO,bw,boff,acs,addr};
1774
1775CSTATE mwait_cstate = {idx,lat,pw};
1776CSTATE io_cstate = {idx,lat,pw};
1777
1778{
1779cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate;
1780cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas;
1781cpu->pkg_mwait_cstates.num_cstates++;
1782}
1783
1784{
1785cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate;
1786cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas;
1787cpu->pkg_io_cstates.num_cstates++;
1788}
1789num_cstates++;
1790
1791if (num_cstates >= MAX_CSTATES)
1792{
1793break;
1794}
1795}
1796}
1797}
1798}
1799
1800if (num_cstates)
1801{
1802return (1);
1803}
1804}
1805}
1806}
1807
1808{
1809static const ACPI_GENERIC_ADDRESS mwait_gas[] = {
1810{GAS_TYPE_FFH,1,2,1,0x00}, // processor C1
1811{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C2
1812{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C3
1813{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C4
1814{GAS_TYPE_FFH,1,2,1,0x20}, // processor C6
1815{GAS_TYPE_FFH,1,2,1,0x30}, // processor C7
1816};
1817
1818static const ACPI_GENERIC_ADDRESS io_gas[] = {
1819{GAS_TYPE_FFH, 0,0,0,0x00}, // processor C1
1820{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C2 or processor C2
1821{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C3
1822{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C4 as ACPI C4
1823{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C6
1824{GAS_TYPE_SYSTEM_IO,8,0,0,0x16}, // processor C7
1825};
1826
1827static const CSTATE mwait_cstate [] = {
1828{1,0x01,0x3e8}, // processor C1
1829{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
1830{3,0x40,0x1f4}, // processor C3 as ACPI C3
1831{4,0x40,0x1f4}, // processor C4
1832{6/*was 3*/,0x60,0x15e}, // processor C6
1833{7/*was 3*/,0x60,0x0c8}, // processor C7
1834};
1835
1836static const CSTATE io_cstate [] = {
1837{1,0x01,0x3e8}, // processor C1
1838{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
1839{3,0x40,0x1f4}, // processor C3 as ACPI C3
1840{4,0x40,0x1f4}, // processor C4
1841{6/*was 3*/,0x60,0x15e}, // processor C6
1842{7/*was 3*/,0x60,0x0c8}, // processor C7
1843};
1844
1845static const U32 cstate_2_index [] = {0,0,0,1,2,3,4,5};
1846
1847// Build C-state table info based on verified options
1848
1849// Desired state for the processor core C3 state included in the _CST as an
1850// ACPI C2 state.
1851// 1= processor core C3 can be used as an ACPI C2 state
1852// 0= processor core C3 cannot be used as an ACPI C2 state
1853int c2_enabled = 0;
1854
1855// Desired state for the processor core C3 state included in the _CST
1856// 0= processor core C3 cannot be used as an ACPI C state
1857// 2= processor core C3 can be used as an ACPI C2 state
1858// 3= processor core C3 can be used as an ACPI C3 state
1859// 4= processor core C3 can be used as an ACPI C2 state
1860// if Invariant APIC Timer detected, else not used as ACPI C state
1861// 5= processor core C3 can be used as an ACPI C2 state
1862// if Invariant APIC Timer detected, else APIC C3 state
1863// 6= processor core C3 can be used as an ACPI C4 state
1864int c3_enabled = 3;
1865
1866// Desired state for the processor core C3 state included in the _CST as an
1867// ACPI C4 state.
1868// 1= processor core C3 can be used as an ACPI C4 state
1869// 0= processor core C3 cannot be used as an ACPI C4 state
1870int c4_enabled = 0;
1871
1872// Desired state for the processor core C6 state included in the _CST as an
1873// ACPI C3 state.
1874// 1= processor core C6 can be used as an ACPI C3 state
1875// 0= processor core C6 cannot be used as an ACPI C3 state
1876int c6_enabled = 0;
1877
1878// Desired state for the processor core C7 state included in the _CST as an
1879// ACPI C3 state.
1880// 1= processor core C7 can be used as an ACPI C7 state
1881// 0= processor core C7 cannot be used as an ACPI C7 state
1882int c7_enabled = 0;
1883
1884{
1885bool tmpval;
1886
1887
1888if (getBoolForKey(kEnableC2State, &tmpval, &bootInfo->bootConfig))
1889{
1890c2_enabled = tmpval;
1891}
1892
1893if (!getIntForKey("C3StateOption", &c3_enabled, &bootInfo->bootConfig))
1894{
1895c3_enabled = (getBoolForKey(kEnableC3State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 3 : 0;
1896}
1897if (c3_enabled == 6)
1898{
1899c4_enabled = 1;
1900}
1901else
1902{
1903c4_enabled = (getBoolForKey(kEnableC4State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
1904}
1905c6_enabled = (getBoolForKey(kEnableC6State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
1906c7_enabled = (getBoolForKey(kEnableC7State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
1907}
1908
1909cpu->pkg_mwait_cstates.num_cstates = 0;
1910{
1911{
1912cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C1]];
1913cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C1]];
1914cpu->pkg_mwait_cstates.num_cstates++;
1915}
1916if (((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled)) && ((c3_enabled == 2) ||
1917 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
1918{
1919cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
1920cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C2]];
1921cpu->pkg_mwait_cstates.num_cstates++;
1922}
1923if (cpu->core_c4_supported && c4_enabled)
1924{
1925
1926cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C4]];
1927cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C4]];
1928cpu->pkg_mwait_cstates.num_cstates++;
1929
1930}
1931else
1932{
1933
1934if (cpu->core_c3_supported && ((c3_enabled == 3) ||
1935 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
1936{
1937cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
1938cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C3]];
1939cpu->pkg_mwait_cstates.num_cstates++;
1940}
1941}
1942
1943
1944if (cpu->core_c6_supported && c6_enabled)
1945{
1946cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C6]];
1947cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C6]];
1948cpu->pkg_mwait_cstates.num_cstates++;
1949}
1950if (cpu->core_c7_supported && c7_enabled)
1951{
1952cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C7]];
1953cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C7]];
1954cpu->pkg_mwait_cstates.num_cstates++;
1955}
1956}
1957
1958cpu->pkg_io_cstates.num_cstates = 0;
1959{
1960{
1961cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C1]];
1962cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C1]];
1963cpu->pkg_io_cstates.num_cstates++;
1964}
1965if ((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled || (c3_enabled == 2) ||
1966 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
1967{
1968cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
1969cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C2]];
1970cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
1971cpu->pkg_io_cstates.num_cstates++;
1972}
1973if (cpu->core_c4_supported && c4_enabled)
1974{
1975
1976cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C4]];
1977cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C4]];
1978cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
1979cpu->pkg_io_cstates.num_cstates++;
1980
1981}
1982else
1983{
1984
1985if (cpu->core_c3_supported && ((c3_enabled == 3) ||
1986 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
1987{
1988cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
1989cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C3]];
1990cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
1991cpu->pkg_io_cstates.num_cstates++;
1992}
1993}
1994
1995if (cpu->core_c6_supported && c6_enabled)
1996{
1997cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C6]];
1998cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C6]];
1999cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2000cpu->pkg_io_cstates.num_cstates++;
2001}
2002if (cpu->core_c7_supported && c7_enabled)
2003{
2004cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C7]];
2005cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C7]];
2006cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2007cpu->pkg_io_cstates.num_cstates++;
2008}
2009}
2010}
2011
2012return (1);
2013}
2014
2015#if BUILD_ACPI_TSS
2016//-----------------------------------------------------------------------------
2017static U32 BuildTstateInfo(CPU_DETAILS * cpu)
2018{
2019 // Coarse grained clock modulation is available if cpuid.6.eax[5] = 0
2020 // Max of 8 T-states using 12.5% increments
2021 static const TSTATE tstate_coarse_grain [] = {
2022 {100,0,0,0x00,0},
2023 { 88,0,0,0x1e,0},
2024 { 75,0,0,0x1c,0},
2025 { 63,0,0,0x1a,0},
2026 { 50,0,0,0x18,0},
2027 { 38,0,0,0x16,0},
2028 { 25,0,0,0x14,0},
2029 { 13,0,0,0x12,0},
2030 };
2031
2032 // Fine grained clock modulation is available if cpuid.6.eax[5] = 1
2033 // Max of 15 T-states using 6.25% increments
2034 static const TSTATE tstate_fine_grain [] = {
2035 {100,0,0,0x00,0},
2036 { 94,0,0,0x1f,0},
2037 { 88,0,0,0x1e,0},
2038 { 81,0,0,0x1d,0},
2039 { 75,0,0,0x1c,0},
2040 { 69,0,0,0x1b,0},
2041 { 63,0,0,0x1a,0},
2042 { 56,0,0,0x19,0},
2043 { 50,0,0,0x18,0},
2044 { 44,0,0,0x17,0},
2045 { 38,0,0,0x16,0},
2046 { 31,0,0,0x15,0},
2047 { 25,0,0,0x14,0},
2048 { 19,0,0,0x13,0},
2049 { 13,0,0,0x12,0},
2050 };
2051
2052 // Build T-state table info based on verified options
2053 U32 num_cpu;
2054 const TSTATE * tstate;
2055 U32 num_tstates;
2056
2057 for (num_cpu = 0; num_cpu < cpu_map_count; num_cpu ++)
2058 {
2059 // Check if fine or coarse grained clock modulation is available
2060 if (Platform->CPU.fine_grain_clock_mod)
2061 {
2062 // Fine grain thermal throttling is available
2063 num_tstates = 15;
2064 tstate = tstate_fine_grain;
2065 }
2066 else
2067 {
2068 // Coarse grain thermal throttling is available
2069 num_tstates = 8;
2070 tstate = tstate_coarse_grain;
2071 }
2072
2073 cpu->pkg_tstates.num_tstates = num_tstates;
2074 {
2075 U32 index;
2076 for (index = 0; index < num_tstates; index++)
2077 {
2078 cpu->pkg_tstates.tstate[index] = tstate[index];
2079 cpu->pkg_tstates.tstate[index].power = 1000 * (compute_tdp(cpu) * (num_tstates - index)) / num_tstates;
2080 }
2081 }
2082
2083
2084 }
2085 return (1);
2086}
2087#endif // BUILD_ACPI_TSS
2088
2089//-----------------------------------------------------------------------------
2090U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 nb_cpu)
2091{
2092 void *current;
2093 void *currentOut;
2094 void *end;
2095 void * endOut;
2096
2097 U32 LOCAL_APIC_NMI_CNT = 0, LOCAL_SAPIC_CNT = 0, INT_SRC_CNT = 0, Length = 0;
2098
2099 // Quick sanity check for a valid MADT
2100 if (madt == 0ul || !nb_cpu)
2101 return (0);
2102
2103 // Confirm a valid MADT buffer was provided
2104 if (!buffer)
2105 {
2106 printf("Error: Invalid Buffer Address for MADT\n");
2107 return(0);
2108 }
2109
2110 // Confirm a valid MADT buffer length was provided
2111 if (!bufferSize)
2112 {
2113 printf("Error: Invalid Buffer Length for MADT\n");
2114 return(0);
2115 }
2116
2117 madt_info->lapic_count = 0;
2118
2119 memcpy(buffer, madt, sizeof(ACPI_TABLE_MADT));
2120
2121 // Search MADT for Sub-tables with needed data
2122 current = madt + 1;
2123 currentOut = buffer + sizeof(ACPI_TABLE_MADT) ;
2124
2125 end = (U8 *) madt + madt->Header.Length;
2126 endOut = (U8 *)buffer + bufferSize;
2127
2128 // Check to confirm no MADT buffer overflow
2129 if ( (U8 *)currentOut > (U8 *)endOut )
2130 {
2131 printf("Error: MADT Buffer Length exceeded available space \n");
2132 return(0);
2133 }
2134
2135 Length += sizeof(ACPI_TABLE_MADT);
2136
2137 while (current < end)
2138{
2139 ACPI_SUBTABLE_HEADER *subtable = current;
2140 ACPI_SUBTABLE_HEADER *subtableOut = currentOut;
2141
2142
2143 switch (subtable->Type)
2144{
2145
2146case ACPI_MADT_TYPE_LOCAL_APIC:
2147 {
2148
2149 // Process sub-tables with Type as 0: Processor Local APIC
2150 ACPI_MADT_LOCAL_APIC *lapic = current;
2151 current = lapic + 1;
2152
2153 if (!(lapic->LapicFlags & ACPI_MADT_ENABLED))
2154 continue;
2155
2156 if (madt_info->lapic_count >= nb_cpu)
2157 continue;
2158
2159 // copy subtable
2160 {
2161
2162 memcpy(currentOut, lapic, lapic->Header.Length);
2163
2164 currentOut = currentOut + lapic->Header.Length;
2165
2166 // Check to confirm no MADT buffer overflow
2167 if ( (U8 *)currentOut > (U8 *)endOut )
2168 {
2169 printf("Error: MADT Buffer Length exceeded available space \n");
2170 return(0);
2171 }
2172 }
2173
2174 {
2175 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
2176
2177 lapic_info->processorId = lapic->ProcessorId;
2178 lapic_info->apicId = lapic->Id;
2179 lapic_info->madt_type = ACPI_MADT_TYPE_LOCAL_APIC;
2180 }
2181
2182 madt_info->lapic_count++;
2183
2184 Length += lapic->Header.Length;
2185
2186 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2187 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
2188 return (0);
2189
2190 break;
2191 }
2192
2193case ACPI_MADT_TYPE_X2APIC:
2194 {
2195
2196 // Process sub-tables with Type as 9: Processor X2APIC
2197 ACPI_MADT_X2APIC *x2apic = current;
2198 current = x2apic + 1;
2199
2200 if (!(x2apic->x2apicFlags & ACPI_MADT_ENABLED))
2201 continue;
2202
2203 if (madt_info->lapic_count >= nb_cpu)
2204 continue;
2205
2206 // copy subtable
2207 {
2208 memcpy(currentOut, x2apic, x2apic->Header.Length);
2209
2210 currentOut = currentOut + x2apic->Header.Length;
2211
2212 // Check to confirm no MADT buffer overflow
2213 if ( (U8 *)currentOut > (U8 *)endOut )
2214 {
2215 printf("Error: MADT Buffer Length exceeded available space \n");
2216 return(0);
2217 }
2218
2219 }
2220
2221 {
2222 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
2223
2224 lapic_info->uid = x2apic->UID;
2225 lapic_info->apicId = x2apic->x2apicId;
2226 lapic_info->madt_type = ACPI_MADT_TYPE_X2APIC;
2227 }
2228
2229 madt_info->lapic_count++;
2230
2231 Length += x2apic->Header.Length;
2232
2233 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2234 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
2235 return (0);
2236
2237 break;
2238 }
2239
2240 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
2241 {
2242 // Process sub-tables with Type as 4: Local APIC NMI
2243 ACPI_MADT_LOCAL_APIC_NMI *nmi = current;
2244 current = nmi + 1;
2245 /*
2246 if (!(nmi->IntiFlags & ACPI_MADT_ENABLED))
2247 continue;
2248 */
2249 if (LOCAL_APIC_NMI_CNT >= nb_cpu)
2250 continue;
2251
2252 memcpy(currentOut, nmi, nmi->Header.Length);
2253
2254 currentOut = currentOut + nmi->Header.Length;
2255
2256 // Check to confirm no MADT buffer overflow
2257 if ( (U8 *)currentOut > (U8 *)endOut )
2258 {
2259 printf("Error: MADT Buffer Length exceeded available space \n");
2260 return(0);
2261 }
2262
2263
2264 LOCAL_APIC_NMI_CNT++;
2265
2266 Length += nmi->Header.Length;
2267
2268 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2269 if (LOCAL_APIC_NMI_CNT > MAX_LOGICAL_CPU)
2270 return (0);
2271
2272 break;
2273 }
2274
2275 case ACPI_MADT_TYPE_LOCAL_SAPIC:
2276 {
2277 // Process sub-tables with Type as 7: Local Sapic
2278 ACPI_MADT_LOCAL_SAPIC *sapic = current;
2279 current = sapic + 1;
2280 /*
2281 if (!(sapic->LapicFlags & ACPI_MADT_ENABLED))
2282 continue;
2283 */
2284 if (LOCAL_SAPIC_CNT >= nb_cpu)
2285 continue;
2286
2287 memcpy(currentOut, sapic, sapic->Header.Length);
2288
2289 currentOut = currentOut + sapic->Header.Length;
2290
2291 // Check to confirm no MADT buffer overflow
2292 if ( (U8 *)currentOut > (U8 *)endOut )
2293 {
2294 printf("Error: MADT Buffer Length exceeded available space \n");
2295 return(0);
2296 }
2297
2298
2299 LOCAL_SAPIC_CNT++;
2300
2301 Length += sapic->Header.Length;
2302
2303 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2304 if (LOCAL_SAPIC_CNT > MAX_LOGICAL_CPU)
2305 return (0);
2306
2307 break;
2308 }
2309
2310 case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
2311 {
2312 // Process sub-tables with Type as 8: Platform Interrupt Source
2313 ACPI_MADT_INTERRUPT_SOURCE *intsrc = current;
2314 current = intsrc + 1;
2315 /*
2316 if (!(intsrc->IntiFlags & ACPI_MADT_ENABLED))
2317 continue;
2318 */
2319 if (INT_SRC_CNT >= nb_cpu)
2320 continue;
2321
2322 memcpy(currentOut, intsrc, intsrc->Header.Length);
2323
2324 currentOut = currentOut + intsrc->Header.Length;
2325
2326 // Check to confirm no MADT buffer overflow
2327 if ( (U8 *)currentOut > (U8 *)endOut )
2328 {
2329 printf("Error: MADT Buffer Length exceeded available space \n");
2330 return(0);
2331 }
2332
2333
2334 INT_SRC_CNT++;
2335
2336 Length += intsrc->Header.Length;
2337
2338 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2339 if (INT_SRC_CNT > MAX_LOGICAL_CPU)
2340 return (0);
2341
2342 break;
2343 }
2344
2345default:
2346 {
2347
2348 // Process all other sub-tables
2349 current = (U8 *) subtable + subtable->Length;
2350 currentOut = (U8 *) subtableOut + subtable->Length;
2351
2352 memcpy(subtableOut, subtable, subtable->Length);
2353
2354 // Check to confirm no MADT buffer overflow
2355 if ( (U8 *)currentOut > (U8 *)endOut )
2356 {
2357 printf("Error: MADT Buffer Length exceeded available space \n");
2358 return(0);
2359 }
2360
2361 Length += subtable->Length;
2362
2363 break;
2364 }
2365 } // switch
2366
2367 } // while
2368
2369 {
2370 ACPI_TABLE_MADT * new_madt = (ACPI_TABLE_MADT * )buffer;
2371
2372 // Update the Lenght of the new MADT table
2373 new_madt->Header.Length = Length;
2374
2375 // Update the checksum of the new MADT table
2376SetChecksum(&new_madt->Header);
2377 }
2378
2379 return (1);
2380}
2381
2382static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info)
2383{
2384 DBG("Build MADT\n");
2385
2386ACPI_TABLE_MADT * madt_file = (void*)0ul;
2387ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
2388 bool oem_apic=false;
2389 U8 new_table_index = 0;
2390
2391 // Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
2392 if (generate_cpu_map_from_acpi(dsdt) != 0)
2393 {
2394 return(0);
2395 }
2396
2397 {
2398bool tmpval;
2399oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
2400}
2401
2402 if (oem_apic == true)
2403 {
2404 return(0);
2405 }
2406
2407 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
2408{
2409 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
2410
2411 new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
2412}
2413 else
2414 {
2415 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
2416
2417 new_table_index = get_0ul_index_in_list(new_table_list, true);
2418
2419 // Check to confirm space is available
2420 if (new_table_index == ACPI_TABLE_LIST_FULL)
2421 {
2422 printf("Error: not enought reserved space in the new acpi list for the MADT table,\n ");
2423 printf(" please increase the RESERVED_AERA\n");
2424 return(0);
2425 }
2426 }
2427
2428 // Create buffer for MADT
2429 U8 memory_for_madt[2 * 1024];
2430
2431
2432 // Build the new MADT
2433 if ( (ProcessMadt(MadtPointer, madt_info, memory_for_madt, sizeof(memory_for_madt), cpu_map_count))== 0)
2434{
2435printf("Error: Failed to build MADT table\n");
2436return (0);
2437}
2438
2439// insert MADT in the new_table_list
2440{
2441// Create pointer to MADT just built in the stack buffer
2442ACPI_TABLE_MADT * old_madt = (ACPI_TABLE_MADT *)memory_for_madt;
2443
2444// Reserved kernel memory for the madt table
2445ACPI_TABLE_MADT *new_madt = (ACPI_TABLE_MADT *)AllocateKernelMemory(old_madt->Header.Length);
2446
2447if (!new_madt)
2448{
2449printf("Unable to allocate kernel memory for MADT ");
2450return (0);
2451}
2452// Move the old stack buffer to kernel memory
2453memcpy(new_madt, old_madt, old_madt->Header.Length);
2454
2455// Add the new madt into an empty space of the new_table_list
2456new_table_list[new_table_index] = (U32)new_madt;
2457}
2458
2459 verbose ("MADT table successfully patched\n");
2460return(1);
2461}
2462
2463static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates )
2464{
2465DBG("Processing SSDT\n");
2466
2467if (Platform->CPU.Vendor != 0x756E6547) {
2468verbose ("Not an Intel platform: SSDT will not be generated !!!\n");
2469return(0);
2470}
2471
2472if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {
2473verbose ("Unsupported CPU: SSDT will not be generated !!!\n");
2474return(0);
2475}
2476
2477if (dsdt == (void *)0ul) {
2478verbose ("DSDT not found: SSDT will not be generated !!!\n");
2479return (0);
2480}
2481
2482// Get an empty space in the new_talbe_list (true = allow reserved space)
2483U8 empty = get_0ul_index_in_list(new_table_list, true);
2484
2485// Check to confirm space is available
2486if (empty == ACPI_TABLE_LIST_FULL)
2487{
2488printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n ");
2489printf(" please increase the RESERVED_AERA\n");
2490return(0);
2491}
2492
2493// Create buffer for SSDT
2494U8 memory_for_ssdt[20 * 1024];
2495
2496// Build the SSDT
2497if ( (BuildSsdt(madt_info, dsdt, memory_for_ssdt, sizeof(memory_for_ssdt), enable_cstates, enable_pstates, enable_tstates)) == 0)
2498{
2499printf("Error: Failed to build SSDT table\n");
2500return (0);
2501}
2502
2503// insert SSDT in the new_table_list
2504{
2505// Create pointer to SSDT just built in the stack buffer
2506ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
2507
2508// Reserved kernel memory for the ssdt table
2509ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
2510
2511if (!new_ssdt)
2512{
2513printf("Unable to allocate kernel memory for SSDT ");
2514return (0);
2515}
2516// Move the old stack buffer to kernel memory
2517memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
2518
2519// Add the new ssdt into an empty space of the new_table_list
2520new_table_list[empty] = (U32)new_ssdt;
2521}
2522
2523verbose ("SSDT table generated successfully\n");
2524return(1);
2525}
2526
2527//-----------------------------------------------------------------------------
2528static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
2529{
2530ACPI_SCOPE * scope = current;
2531current = scope + 1;
2532
2533scope->scopeOpcode = AML_SCOPE_OP;
2534scope->rootChar = AML_ROOT_PREFIX;
2535
2536if (aslCpuNamePath->seg_count == 1)
2537{
2538DUAL_NAME_PATH * dualNamePath = current;
2539current = dualNamePath + 1;
2540dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
2541dualNamePath->nameseg[0] = cpu_namespace;
2542dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
2543}
2544else
2545{
2546MULTI_NAME_PATH * multiNamePath = current;
2547current = multiNamePath + 1;
2548multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
2549// the nameseg count includes the root prefix and all other namesegs
2550multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
2551multiNamePath->nameseg[0] = cpu_namespace;
2552{
2553U32 i;
2554for (i=0; i<aslCpuNamePath->seg_count; i++)
2555multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
2556}
2557}
2558return (current);
2559}
2560//-----------------------------------------------------------------------------
2561static void * buildPDC(void * current)
2562{
2563ACPI_METHOD * pdc = current;
2564current = buildMethod(current, NAMESEG("_PDC"), 1);
2565
2566// CreateDWordField (Arg0, 0x08, CAPA)
2567current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2568current = buildOpCode(current, AML_ARG0_OP);
2569current = buildByteConst(current, 0x08);
2570current = buildNameSeg(current, NAMESEG("CAPA"));
2571
2572// Store (CAPA, TYPE)
2573current = buildOpCode(current, AML_STORE_OP);
2574current = buildNameSeg(current, NAMESEG("CAPA"));
2575current = buildNameSeg(current, NAMESEG("TYPE"));
2576
2577// CreateDWordField (Arg0, 0x00, REVS)
2578current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2579current = buildOpCode(current, AML_ARG0_OP);
2580current = buildByteConst(current, 0x00);
2581current = buildNameSeg(current, NAMESEG("REVS"));
2582
2583// CreateDWordField (Arg0, 0x04, SIZE)
2584current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2585current = buildOpCode(current, AML_ARG0_OP);
2586current = buildByteConst(current, 0x04);
2587current = buildNameSeg(current, NAMESEG("SIZE"));
2588
2589// Store(SizeOf(Arg0), Local0)
2590current = buildOpCode(current, AML_STORE_OP);
2591current = buildOpCode(current, AML_SIZEOF_OP);
2592current = buildOpCode(current, AML_ARG0_OP);
2593current = buildOpCode(current, AML_LOCAL0_OP);
2594
2595// Store(Subtract(Local0, 0x08),Local1)
2596current = buildOpCode(current, AML_STORE_OP);
2597current = buildOpCode(current, AML_SUBTRACT_OP);
2598current = buildOpCode(current, AML_LOCAL0_OP);
2599current = buildByteConst(current, 0x08);
2600current = buildOpCode(current, AML_ZERO_OP);
2601current = buildOpCode(current, AML_LOCAL1_OP);
2602
2603// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
2604current = buildOpCode(current, AML_EXT_OP_PREFIX);
2605current = buildOpCode(current, AML_CREATE_FIELD_OP);
2606current = buildOpCode(current, AML_ARG0_OP);
2607current = buildByteConst(current, 0x40);
2608current = buildOpCode(current, AML_MULTIPLY_OP);
2609current = buildOpCode(current, AML_LOCAL1_OP);
2610current = buildByteConst(current, 0x08);
2611current = buildOpCode(current, AML_ZERO_OP);
2612current = buildNameSeg(current, NAMESEG("TEMP"));
2613
2614// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
2615// Create STS0 as named buffer
2616current = buildNamePath(current, NAMESEG("STS0"));
2617{
2618ACPI_SMALL_BUFFER * buff = current;
2619current = buildSmallBuffer(current);
2620
2621// count of buffer elements
2622current = buildByteConst(current, 4);
2623
2624current = buildOpCode(current, AML_ZERO_OP);
2625current = buildOpCode(current, AML_ZERO_OP);
2626current = buildOpCode(current, AML_ZERO_OP);
2627current = buildOpCode(current, AML_ZERO_OP);
2628{
2629U32 length = (U8 *)current - (U8 *)buff;
2630buff->packageLength = (U8)length - 1;
2631}
2632}
2633
2634//Concatenate (STS0, TEMP, Local2)
2635current = buildOpCode(current, AML_CONCAT_OP);
2636current = buildNameSeg(current, NAMESEG("STS0"));
2637current = buildNameSeg(current, NAMESEG("TEMP"));
2638current = buildOpCode(current, AML_LOCAL2_OP);
2639
2640//_OSC (Buffer (0x10)
2641// {
2642// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2643// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2644// }, REVS, SIZE, Local2)
2645current = buildNameSeg(current, NAMESEG("_OSC"));
2646{
2647ACPI_SMALL_BUFFER * buff = current;
2648current = buildSmallBuffer(current);
2649
2650// count of buffer elements
2651current = buildByteConst(current, 0x10);
2652
2653current = buildOpCode(current, 0x16);
2654current = buildOpCode(current, 0xa6);
2655current = buildOpCode(current, 0x77);
2656current = buildOpCode(current, 0x40);
2657current = buildOpCode(current, 0x0c);
2658current = buildOpCode(current, 0x29);
2659current = buildOpCode(current, 0xbe);
2660current = buildOpCode(current, 0x47);
2661current = buildOpCode(current, 0x9e);
2662current = buildOpCode(current, 0xbd);
2663current = buildOpCode(current, 0xd8);
2664current = buildOpCode(current, 0x70);
2665current = buildOpCode(current, 0x58);
2666current = buildOpCode(current, 0x71);
2667current = buildOpCode(current, 0x39);
2668current = buildOpCode(current, 0x53);
2669{
2670U32 length = (U8 *)current - (U8 *)buff;
2671buff->packageLength = (U8)length - 1;
2672}
2673}
2674current = buildNameSeg(current, NAMESEG("REVS"));
2675current = buildNameSeg(current, NAMESEG("SIZE"));
2676current = buildOpCode(current, AML_LOCAL2_OP);
2677
2678// Update package length in PDC object
2679//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
2680setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
2681
2682return(current);
2683}
2684
2685//-----------------------------------------------------------------------------
2686static void * buildOSC(void * current)
2687{
2688//
2689//
2690ACPI_METHOD * osc = current;
2691current = buildMethod(current, NAMESEG("_OSC"), 4);
2692
2693// CreateDWordField (Arg3, 0x04, CAPA)
2694current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2695current = buildOpCode(current, AML_ARG3_OP);
2696current = buildByteConst(current, 0x04);
2697current = buildNameSeg(current, NAMESEG("CAPA"));
2698
2699// Store (CAPA, TYPE)
2700current = buildOpCode(current, AML_STORE_OP);
2701current = buildNameSeg(current, NAMESEG("CAPA"));
2702current = buildNameSeg(current, NAMESEG("TYPE"));
2703
2704// CreateDWordField (Arg3, 0x00, STS0)
2705current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2706current = buildOpCode(current, AML_ARG3_OP);
2707current = buildByteConst(current, 0x00);
2708current = buildNameSeg(current, NAMESEG("STS0"));
2709
2710// CreateDWordField (Arg3, 0x04, CAP0)
2711current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2712current = buildOpCode(current, AML_ARG3_OP);
2713current = buildByteConst(current, 0x04);
2714current = buildNameSeg(current, NAMESEG("CAP0"));
2715
2716// CreateDWordField (Arg0, 0x00, IID0)
2717current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2718current = buildOpCode(current, AML_ARG0_OP);
2719current = buildByteConst(current, 0x00);
2720current = buildNameSeg(current, NAMESEG("IID0"));
2721
2722// CreateDWordField (Arg0, 0x04, IID1)
2723current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2724current = buildOpCode(current, AML_ARG0_OP);
2725current = buildByteConst(current, 0x04);
2726current = buildNameSeg(current, NAMESEG("IID1"));
2727
2728// CreateDWordField (Arg0, 0x08, IID2)
2729current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2730current = buildOpCode(current, AML_ARG0_OP);
2731current = buildByteConst(current, 0x08);
2732current = buildNameSeg(current, NAMESEG("IID2"));
2733
2734// CreateDWordField (Arg0, 0x0C, IID3)
2735current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2736current = buildOpCode(current, AML_ARG0_OP);
2737current = buildByteConst(current, 0x0C);
2738current = buildNameSeg(current, NAMESEG("IID3"));
2739
2740// Name (UID0, Buffer (0x10)
2741// {
2742// 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2743// 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2744// })
2745current = buildNamePath(current, NAMESEG("UID0"));
2746{
2747ACPI_SMALL_BUFFER * buff = current;
2748current = buildSmallBuffer(current);
2749
2750// count of buffer elements
2751current = buildByteConst(current, 0x10);
2752
2753current = buildOpCode(current, 0x16);
2754current = buildOpCode(current, 0xa6);
2755current = buildOpCode(current, 0x77);
2756current = buildOpCode(current, 0x40);
2757current = buildOpCode(current, 0x0c);
2758current = buildOpCode(current, 0x29);
2759current = buildOpCode(current, 0xbe);
2760current = buildOpCode(current, 0x47);
2761current = buildOpCode(current, 0x9e);
2762current = buildOpCode(current, 0xbd);
2763current = buildOpCode(current, 0xd8);
2764current = buildOpCode(current, 0x70);
2765current = buildOpCode(current, 0x58);
2766current = buildOpCode(current, 0x71);
2767current = buildOpCode(current, 0x39);
2768current = buildOpCode(current, 0x53);
2769
2770{
2771U32 length = (U8 *)current - (U8 *)buff;
2772buff->packageLength = (U8)length - 1;
2773}
2774}
2775
2776// CreateDWordField (UID0, 0x00, EID0)
2777current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2778current = buildOpCode(current, AML_ARG0_OP);
2779current = buildByteConst(current, 0x00);
2780current = buildNameSeg(current, NAMESEG("EID0"));
2781
2782// CreateDWordField (UID0, 0x04, EID1)
2783current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2784current = buildOpCode(current, AML_ARG0_OP);
2785current = buildByteConst(current, 0x04);
2786current = buildNameSeg(current, NAMESEG("EID1"));
2787
2788// CreateDWordField (UID0, 0x08, EID2)
2789current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2790current = buildOpCode(current, AML_ARG0_OP);
2791current = buildByteConst(current, 0x08);
2792current = buildNameSeg(current, NAMESEG("EID2"));
2793
2794// CreateDWordField (UID0, 0x0C, EID3)
2795current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2796current = buildOpCode(current, AML_ARG0_OP);
2797current = buildByteConst(current, 0x0C);
2798current = buildNameSeg(current, NAMESEG("EID3"));
2799
2800// If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)),
2801// LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3)))))
2802// {
2803// Store (0x06, Index (STS0, 0x00))
2804// Return (Arg3)
2805// }
2806{
2807current = buildOpCode(current, AML_IF_OP);
2808{
2809ACPI_PACKAGE_LENGTH * packageLength = current;
2810current = buildPackageLength(current, 0);
2811
2812current = buildOpCode(current, AML_LNOT_OP);
2813current = buildOpCode(current, AML_LAND_OP);
2814current = buildOpCode(current, AML_LAND_OP);
2815current = buildOpCode(current, AML_LEQUAL_OP);
2816current = buildNameSeg(current, NAMESEG("IID0"));
2817current = buildNameSeg(current, NAMESEG("EID0"));
2818
2819current = buildOpCode(current, AML_LEQUAL_OP);
2820current = buildNameSeg(current, NAMESEG("IID1"));
2821current = buildNameSeg(current, NAMESEG("EID1"));
2822
2823current = buildOpCode(current, AML_LAND_OP);
2824current = buildOpCode(current, AML_LEQUAL_OP);
2825current = buildNameSeg(current, NAMESEG("IID2"));
2826current = buildNameSeg(current, NAMESEG("EID2"));
2827
2828current = buildOpCode(current, AML_LEQUAL_OP);
2829current = buildNameSeg(current, NAMESEG("IID3"));
2830current = buildNameSeg(current, NAMESEG("EID3"));
2831
2832// Store (0x06, Index (STS0, 0x00))
2833current = buildOpCode(current, AML_STORE_OP);
2834current = buildByteConst(current, 0x06);
2835current = buildOpCode(current, AML_INDEX_OP);
2836current = buildNameSeg(current, NAMESEG("STS0"));
2837current = buildByteConst(current, 0x00);
2838current = buildOpCode(current, AML_ZERO_OP);
2839
2840// Return (Arg3)
2841current = buildReturnOpcode(current, AML_ARG3_OP);
2842
2843setPackageLength(packageLength,
2844 (U8 *)current - (U8 *)packageLength);
2845}
2846}
2847
2848// If (LNotEqual (Arg1, 0x01))
2849// {
2850// Store (0x0A, Index (STS0, 0x00))
2851// Return (Arg3)
2852// }
2853{
2854current = buildOpCode(current, AML_IF_OP);
2855{
2856ACPI_PACKAGE_LENGTH * packageLength = current;
2857current = buildPackageLength(current, 0);
2858
2859// If ("LNotEqual (Arg1, 0x01)")
2860current = buildOpCode(current, AML_LNOT_OP);
2861current = buildOpCode(current, AML_LEQUAL_OP);
2862current = buildOpCode(current, AML_ARG1_OP);
2863current = buildByteConst(current, 0x01);
2864
2865// Store (0x0A, Index (STS0, 0x00))
2866current = buildOpCode(current, AML_STORE_OP);
2867current = buildByteConst(current, 0x0A);
2868current = buildOpCode(current, AML_INDEX_OP);
2869current = buildNameSeg(current, NAMESEG("STS0"));
2870current = buildByteConst(current, 0x00);
2871current = buildOpCode(current, AML_ZERO_OP);
2872
2873// Return (Arg3)
2874current = buildReturnOpcode(current, AML_ARG3_OP);
2875
2876setPackageLength(packageLength,
2877 (U8 *)current - (U8 *)packageLength);
2878}
2879}
2880
2881// If (And (STS0, 0x01))
2882// {
2883// And (CAP0, 0x0BFF, CAP0)
2884// Return (Arg3)
2885// }
2886{
2887current = buildOpCode(current, AML_IF_OP);
2888{
2889ACPI_PACKAGE_LENGTH * packageLength = current;
2890current = buildPackageLength(current, 0);
2891
2892// If ("And (STS0, 0x01)")
2893current = buildOpCode(current, AML_AND_OP);
2894current = buildNameSeg(current, NAMESEG("STS0"));
2895current = buildByteConst(current, 0x01);
2896current = buildOpCode(current, AML_ZERO_OP);
2897
2898// And (CAP0, 0x0BFF, CAP0)
2899current = buildOpCode(current, AML_AND_OP);
2900current = buildNameSeg(current, NAMESEG("CAP0"));
2901current = buildWordConst(current, 0x0BFF);
2902current = buildNameSeg(current, NAMESEG("CAP0"));
2903
2904// Return (Arg3)
2905current = buildReturnOpcode(current, AML_ARG3_OP);
2906
2907setPackageLength(packageLength,
2908 (U8 *)current - (U8 *)packageLength);
2909}
2910}
2911
2912// And (CAP0, 0x0BFF, CAP0)
2913current = buildOpCode(current, AML_AND_OP);
2914current = buildNameSeg(current, NAMESEG("CAP0"));
2915current = buildWordConst(current, 0x0BFF);
2916current = buildNameSeg(current, NAMESEG("CAP0"));
2917
2918// Store (CAP0, TYPE)
2919current = buildOpCode(current, AML_STORE_OP);
2920current = buildNameSeg(current, NAMESEG("CAP0"));
2921current = buildNameSeg(current, NAMESEG("TYPE"));
2922
2923// Return (Arg3)
2924current = buildReturnOpcode(current, AML_ARG3_OP);
2925
2926// Set package length for the OSC object
2927setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength);
2928
2929return(current);
2930}
2931
2932//-----------------------------------------------------------------------------
2933static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates)
2934{
2935//
2936// IF (PSEN)
2937// {
2938// Return (Package of Pstate Packages)
2939// }
2940// Return(Zero)
2941//
2942ACPI_METHOD * pss = current;
2943current = buildMethod(current, NAMESEG("_PSS"), 0);
2944
2945{
2946// "IF" (PSEN) -- IF Opcode
2947current = buildOpCode(current, AML_IF_OP);
2948{
2949ACPI_PACKAGE_LENGTH * packageLength = current;
2950current = buildPackageLength(current, 0);
2951
2952// IF "(PSEN)" -- IF Predicate
2953current = buildNameSeg(current, NAMESEG("PSEN"));
2954
2955{
2956ACPI_RETURN_PACKAGE * returnPkg = current;
2957current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates);
2958
2959// (3.3.3) For each P-state
2960{
2961U32 pstateIndex = 0;
2962for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++)
2963{
2964// (3.3.3.1) Create P-state package
2965ACPI_PSTATE_PACKAGE * pstate = current;
2966current = pstate + 1;
2967
2968setSmallPackage(&pstate->package, 6);
2969pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1);
2970
2971setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz).
2972setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts).
2973setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds).
2974setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds).
2975setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control.
2976
2977setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status.
2978} // for
2979} // for block
2980
2981// (3.3.4) Update package length in return package
2982setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
2983}
2984
2985// "IF (PSEN) and its body" -- Set package length
2986setPackageLength(packageLength,
2987 (U8 *)current - (U8 *)packageLength);
2988}
2989// "Return (ZERO)"
2990current = buildReturnZero(current);
2991}
2992// Set package length for the _PSS object
2993setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength);
2994
2995return(current);
2996}
2997
2998//-----------------------------------------------------------------------------
2999static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination)
3000{
3001// If (And(TYPE, 0x0820))
3002// {
3003// Return (PSD Package)
3004// }
3005// Return(Zero)
3006
3007ACPI_METHOD * psdMethod = current;
3008current = buildMethod(current, NAMESEG("_PSD"), 0);
3009{
3010// "IF" (And(TYPE, 0x0820)) -- IF Opcode
3011current = buildOpCode(current, AML_IF_OP);
3012{
3013ACPI_PACKAGE_LENGTH * packageLength = current;
3014current = buildPackageLength(current, 0);
3015
3016// IF ("And"(TYPE, 0x820)) -- AND Opcode
3017current = buildOpCode(current, AML_AND_OP);
3018
3019// IF (And("TYPE", 0x820)) -- TYPE Term
3020current = buildNameSeg(current, NAMESEG("TYPE"));
3021
3022// IF (And(TYPE, "0x0820")) -- DWORD Value Term
3023current = buildDwordConst(current, 0x820);
3024
3025// IF ("And(TYPE, 0x200)") -- Target for And term (unused)
3026current = buildOpCode(current, AML_ZERO_OP);
3027
3028// Build return package containing PSD package
3029{
3030ACPI_RETURN_PACKAGE * returnPkg = current;
3031current = buildReturnPackage(current, 1);
3032
3033{
3034// Create PSD package
3035ACPI_PSD_PACKAGE * psd = current;
3036current = psd + 1;
3037
3038setSmallPackage(&psd->package, 5);
3039psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1);
3040
3041setByteConst(&psd->NumberOfEntries, 5);
3042setByteConst(&psd->Revision, 0);
3043setDwordConst(&psd->Domain, domain);
3044setDwordConst(&psd->CoordType, pstate_coordination);
3045setDwordConst(&psd->NumProcessors, cpusInDomain);
3046
3047} // PSD package
3048
3049setPackageLength(&returnPkg->package.pkgLength,
3050 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3051}
3052setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3053}
3054// "Return (ZERO)"
3055current = buildReturnZero(current);
3056}
3057// Update length in _PSD method
3058setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength);
3059
3060return(current);
3061}
3062
3063//-----------------------------------------------------------------------------
3064static void * buildPPC(void * current/*, U8 valueToReturn*/)
3065{
3066ACPI_SMALL_METHOD * ppc = current;
3067current = buildSmallMethod(current, NAMESEG("_PPC"), 0);
3068
3069current = buildReturnZero(current);
3070
3071//current = buildReturnOpcode(current, valueToReturn);
3072
3073// Update package length in PPC object
3074ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength );
3075
3076return(current);
3077}
3078
3079#if UNUSED
3080//-----------------------------------------------------------------------------
3081static void * buildPDL(void * current, U8 valueToReturn)
3082{
3083ACPI_SMALL_METHOD * pdl = current;
3084current = buildSmallMethod(current, NAMESEG("_PDL"), 0);
3085
3086current = buildReturnOpcode(current, valueToReturn);
3087
3088// Update package length in PDL object
3089pdl->packageLength = (U8) ( (U8 *)current - (U8 *)&pdl->packageLength );
3090
3091return(current);
3092}
3093#endif
3094
3095//-----------------------------------------------------------------------------
3096static void * buildPCT(void * current)
3097{
3098static const ACPI_GENERIC_ADDRESS pct_gas[] = {
3099{0x7f,0x40,0,0,0x199},
3100{0x7f,0x10,0,0,0x198},
3101};
3102
3103ACPI_SMALL_METHOD * pct = current;
3104current = buildSmallMethod(current, NAMESEG("_PCT"), 0);
3105
3106{
3107ACPI_RETURN_PACKAGE * returnPkg = current;
3108current = buildReturnPackage(current, 2);
3109
3110{
3111ACPI_SMALL_BUFFER * buff = current;
3112current = buildSmallBuffer(current);
3113
3114current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3115current = buildGenericRegister(current, &pct_gas[0]);
3116current = buildEndTag(current);
3117
3118{
3119U32 length = (U8 *)current - (U8 *)buff;
3120buff->packageLength = (U8)length - 1;
3121}
3122}
3123{
3124ACPI_SMALL_BUFFER * buff = current;
3125current = buildSmallBuffer(current);
3126
3127current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3128current = buildGenericRegister(current, &pct_gas[1]);
3129current = buildEndTag(current);
3130
3131{
3132U32 length = (U8 *)current - (U8 *)buff;
3133buff->packageLength = (U8)length - 1;
3134}
3135
3136}
3137
3138setPackageLength(&returnPkg->package.pkgLength,
3139 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3140}
3141
3142// Update package length in PCT object
3143pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength);
3144
3145return(current);
3146}
3147
3148//-----------------------------------------------------------------------------
3149static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate)
3150{
3151//
3152// Build a C-state
3153//
3154ACPI_SMALL_PACKAGE * pkg1 = current;
3155current = buildSmallPackage(current, 4);
3156
3157{
3158{
3159ACPI_SMALL_BUFFER * buffer = current;
3160current = buildSmallBuffer(current);
3161
3162{
3163// Buffer length
3164current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3165current = buildGenericRegister(current, gas);
3166current = buildEndTag(current);
3167}
3168{
3169U32 length = (U8 *)current - (U8 *)buffer;
3170buffer->packageLength = (U8)length - 1;
3171}
3172}
3173
3174{
3175current = buildByteConst(current, cstate->type);
3176current = buildWordConst(current, cstate->latency);
3177current = buildDwordConst(current, cstate->power);
3178}
3179}
3180pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength);
3181
3182return(current);
3183}
3184
3185//-----------------------------------------------------------------------------
3186static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates)
3187{
3188// Create package returning C-states
3189ACPI_RETURN_PACKAGE * returnPkg = current;
3190current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1);
3191
3192{
3193// Include number of C-states
3194current = buildByteConst(current, (U8)pkg_cstates->num_cstates);
3195
3196{
3197U32 cstateIndex = 0;
3198for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3199// Build C-state
3200current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]);
3201}
3202}
3203
3204// Update package length in return package
3205setPackageLength(&returnPkg->package.pkgLength,
3206 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3207
3208return(current);
3209}
3210
3211//-----------------------------------------------------------------------------
3212static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates)
3213{
3214//
3215// IF (CSEN)
3216// {
3217// IF (LAnd(MWOS, And(TYPE, 0x200)))
3218// {
3219// Return package containing MWAIT C-states
3220// }
3221// Return package containing IO C-states
3222// }
3223// Return(Zero)
3224//
3225ACPI_METHOD * cst = current;
3226current = buildMethod(current, NAMESEG("_CST"), 0);
3227{
3228// "IF" CSEN -- IF Opcode
3229current = buildOpCode(current, AML_IF_OP);
3230{
3231ACPI_PACKAGE_LENGTH * packageLength1 = current;
3232current = buildPackageLength(current, 0);
3233
3234// IF "(CSEN)" -- IF Predicate
3235current = buildNameSeg(current, NAMESEG("CSEN"));
3236