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