uint8_t␉acpi_cpu_count = 0;␊ |
char* acpi_cpu_name[32];␊ |
␊ |
void find_acpi_cpu_names(unsigned char* dsdt, int length)␊ |
void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)␊ |
{␊ |
␉int i;␊ |
␉uint32_t i;␊ |
␉␊ |
␉for (i=0; i<length-7; i++) ␊ |
␉{␊ |
␉␉if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP␊ |
␉␉{␊ |
␉␉␉uint8_t offset = i+2+(dsdt[i+2] >> 6) + 1, j;␊ |
␉␉␉uint32_t offset = i + 3 + (dsdt[i+2] >> 6);␊ |
␉␉␉␊ |
␉␉␉bool add_name = true;␊ |
␊ |
␉␉␉uint8_t j;␊ |
␉␉␉␊ |
␉␉␉for (j=0; j<4; j++) ␊ |
␉␉␉{␊ |
␉␉␉␉char c = dsdt[offset+j];␊ |
|
␉␉␉␉if (!aml_isvalidchar(c)) ␊ |
␉␉␉␉{␊ |
␉␉␉␉␉add_name = false;␊ |
␉␉␉␉␉verbose("Invalid characters found in ProcessorOP!\n");␊ |
␉␉␉␉␉verbose("Invalid character found in ProcessorOP 0x%x!\n", c);␊ |
␉␉␉␉␉break;␊ |
␉␉␉␉}␊ |
␉␉␉}␊ |
␉␉␉␊ |
␉␉␉if (add_name && dsdt[offset+5] < 32 ) ␊ |
␉␉␉if (add_name) ␊ |
␉␉␉{␊ |
␉␉␉␉acpi_cpu_name[acpi_cpu_count] = malloc(5);␊ |
␉␉␉␉acpi_cpu_name[acpi_cpu_count] = malloc(4);␊ |
␉␉␉␉memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);␊ |
␉␉␉␉i = offset + 5;␊ |
␉␉␉␉␊ |
␉␉␉␉verbose("Found %c%c%c%c (from DSDT)\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);␊ |
␉␉␉␉verbose("Found ACPI CPU: %c%c%c%c\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);␊ |
␉␉␉␉␊ |
␉␉␉␉if (++acpi_cpu_count == 32) return;␊ |
␉␉␉}␊ |
|
␉␉0x31, 0x03, 0x10, 0x20 ␉␉␉␉␉␉␉/* 1.._␉␉*/␊ |
␉};␊ |
␉␊ |
␉char chunk_name_body[] =␊ |
␉char cstate_resource_template[] = ␊ |
␉{␊ |
␉␉0x5C, 0x5F, 0x50, 0x52, 0x5F, 0x08, 0x43, 0x53, /* \_PR_.CS */␊ |
␉␉0x54, 0x5F␉␉␉␉␉␉␉␉␉␉/* T_␉␉*/␊ |
␉␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, ␊ |
␉␉0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ␊ |
␉␉0x00, 0x00, 0x00, 0x79, 0x00␊ |
␉};␊ |
␊ |
␉if (Platform.CPU.Vendor != 0x756E6547) {␊ |
␉␉verbose ("Not an Intel platform: C-States will not be generated !!!\n");␊ |
␉␉return NULL;␊ |
␉}␊ |
␉␊ |
␉char chunk_c1[] =␊ |
␉{␊ |
␉␉0x12, 0x1C, 0x04, 0x11, 0x14, 0x0A, 0x11, 0x82,␊ |
␉␉0x0C, 0x00, 0x7F, 0x01, 0x02, 0x01, 0x00, 0x00,␊ |
␉␉0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00,␊ |
␉␉0x01, 0x01, 0x0B, 0xE8, 0x03 ␉␉␉␉␉␊ |
␉};␊ |
␉␊ |
␉char chunk_c2[] =␊ |
␉{␊ |
␉␉0x12, 0x1E, 0x04, 0x11, 0x14, 0x0A, 0x11, 0x82,␊ |
␉␉0x0C, 0x00, 0x7F, 0x01, 0x02, 0x01, 0x10, 0x00,␊ |
␉␉0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00,␊ |
␉␉0x0A, 0x02, 0x0A, 0x40, 0x0B, 0xF4, 0x01 ␉␉␉␉␉␊ |
␉};␊ |
␉␊ |
␉char chunk_c3[] =␊ |
␉{␊ |
␉␉0x12, 0x1F, 0x04, 0x11, 0x14, 0x0A, 0x11, 0x82,␊ |
␉␉0x0C, 0x00, 0x7F, 0x01, 0x02, 0x01, 0x20, 0x00,␊ |
␉␉0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00,␊ |
␉␉0x0A, 0x03, 0x0B, 0x60, 0x03, 0x0B, 0x5E, 0x01␊ |
␉};␊ |
␉␉␊ |
␉char chunk_alias[] = ␊ |
␉{␊ |
␉␉0x10, 0x14, 0x5C, 0x2E, 0x5F, 0x50, 0x52, 0x5F, /* ..\._PR_ */␊ |
␉␉0x43, 0x50, 0x55, 0x30, 0x06, 0x43, 0x53, 0x54, /* CPU0.CST */␊ |
␉␉0x5F, 0x5F, 0x43, 0x53, 0x54␉␉␉␉␉/* __CST␉*/␊ |
␉};␊ |
␉␊ |
␉if (fadt == NULL) {␊ |
␉␉verbose ("FACP not exists: C-States not generated !!!\n");␊ |
␉␉verbose ("FACP not exists: C-States will not be generated !!!\n");␊ |
␉␉return NULL;␊ |
␉}␊ |
␉␊ |
␉struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;␊ |
␉␊ |
␉if (dsdt == NULL) {␊ |
␉␉verbose ("DSDT not found: C-States not generated !!!\n");␊ |
␉␉verbose ("DSDT not found: C-States will not be generated !!!\n");␊ |
␉␉return NULL;␊ |
␉}␊ |
␉␊ |
␉if (acpi_cpu_count == 0) ␊ |
␉␉find_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
␉␊ |
␉if (acpi_cpu_count > 0) {␊ |
␉␉bool c2_enabled = fadt->C2_Latency < 100, c3_enabled = fadt->C3_Latency < 1000;␊ |
␉if (acpi_cpu_count > 0) ␊ |
␉{␊ |
␉␉bool c2_enabled = fadt->C2_Latency < 100;␊ |
␉␉bool c3_enabled = fadt->C3_Latency < 1000;␊ |
␉␉bool c4_enabled = false;␊ |
␉␉␊ |
␉␉// Setup C2 Latency␊ |
␉␉if (c2_enabled)␊ |
␉␉␉chunk_c2[27] = fadt->C2_Latency & 0xff;␊ |
␉␉getBoolForKey(kEnableC4States, &c4_enabled, &bootInfo->bootConfig);␊ |
␊ |
␉␉unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);␊ |
␉␉␊ |
␉␉// Setup C3 Latency␊ |
␉␉if (c3_enabled) {␊ |
␉␉␉chunk_c3[27] = fadt->C3_Latency & 0xff;␊ |
␉␉␉chunk_c3[28] = (fadt->C3_Latency >> 8) & 0xff;␊ |
␉␉}␊ |
␉␉struct aml_chunk* root = aml_create_node(NULL);␊ |
␉␉␉aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header␊ |
␉␉␉struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");␊ |
␉␉␉␉struct aml_chunk* name = aml_add_name(scop, "CST_");␊ |
␉␉␉␉␉struct aml_chunk* pack = aml_add_package(name);␊ |
␉␉␉␉␉␉aml_add_byte(pack, cstates_count);␊ |
␉␉␊ |
␉␉// Generating SSDT␊ |
␉␉uint32_t package_length = ␊ |
␉␉␉4 +␊ |
␉␉␉sizeof(chunk_c1) + ␊ |
␉␉␉c2_enabled * sizeof(chunk_c2) +␊ |
␉␉␉c3_enabled * sizeof(chunk_c3);␊ |
␉␉␊ |
␉␉if (package_length > 0x3f) ␊ |
␉␉␉package_length++;␊ |
␉␉␊ |
␉␉uint32_t name_length = ␊ |
␉␉␉1 +␊ |
␉␉␉sizeof(chunk_name_body) + ␊ |
␉␉␉1 + package_length;␊ |
␉␉␊ |
␉␉if (name_length > 0x3f) ␊ |
␉␉␉name_length++;␊ |
␉␉␊ |
␉␉uint32_t ssdt_size = ␊ |
␉␉␉sizeof(ssdt_header) + ␊ |
␉␉␉1 + name_length +␊ |
␉␉␉acpi_cpu_count * sizeof(chunk_alias);␊ |
␉␉␊ |
␉␉struct acpi_2_ssdt *ssdt = (void*)AllocateKernelMemory(ssdt_size);␊ |
␉␉int fd = openmem((char*)ssdt, ssdt_size);␊ |
␉␉␉␉␉␉struct aml_chunk* tmpl = aml_add_package(pack);␊ |
␉␉␉␉␉␉␉cstate_resource_template[11] = 0x00; // C1␊ |
␉␉␉␉␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
␉␉␉␉␉␉␉aml_add_byte(tmpl, 0x01); // C1␊ |
␉␉␉␉␉␉␉aml_add_byte(tmpl, 0x01); // Latency␊ |
␉␉␉␉␉␉␉aml_add_word(tmpl, 0x03e8); // Power␊ |
␊ |
␉␉// Header␊ |
␉␉write(fd, ssdt_header, sizeof(ssdt_header));␊ |
␉␉␉␉␉␉// C2␊ |
␉␉␉␉␉␉if (c2_enabled) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉tmpl = aml_add_package(pack);␊ |
␉␉␉␉␉␉␉␉cstate_resource_template[11] = 0x10; // C2␊ |
␉␉␉␉␉␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
␉␉␉␉␉␉␉␉aml_add_byte(tmpl, 0x02); // C2␊ |
␉␉␉␉␉␉␉␉aml_add_byte(tmpl, fadt->C2_Latency);␊ |
␉␉␉␉␉␉␉␉aml_add_word(tmpl, 0x01f4); // Power␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉// C4␊ |
␉␉␉␉␉␉if (c4_enabled) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉tmpl = aml_add_package(pack);␊ |
␉␉␉␉␉␉␉cstate_resource_template[11] = 0x30; // C4␊ |
␉␉␉␉␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
␉␉␉␉␉␉␉aml_add_byte(tmpl, 0x04); // C4␊ |
␉␉␉␉␉␉␉aml_add_word(tmpl, fadt->C3_Latency / 2); // TODO: right latency for C4␊ |
␉␉␉␉␉␉␉aml_add_byte(tmpl, 0xfa); // Power␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉else␊ |
␉␉␉␉␉␉// C3␊ |
␉␉␉␉␉␉if (c3_enabled) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉tmpl = aml_add_package(pack);␊ |
␉␉␉␉␉␉␉cstate_resource_template[11] = 0x20; // C3␊ |
␉␉␉␉␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
␉␉␉␉␉␉␉aml_add_byte(tmpl, 0x03); // C3␊ |
␉␉␉␉␉␉␉aml_add_word(tmpl, fadt->C3_Latency);␊ |
␉␉␉␉␉␉␉aml_add_word(tmpl, 0x015e); // Power␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉␊ |
␉␉␉␊ |
␉␉␉// Aliaces␊ |
␉␉␉int i;␊ |
␉␉␉for (i = 0; i < acpi_cpu_count; i++) ␊ |
␉␉␉{␊ |
␉␉␉␉char name[9];␊ |
␉␉␉␉sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);␊ |
␉␉␉␉␊ |
␉␉␉␉scop = aml_add_scope(root, name);␊ |
␉␉␉␉␉aml_add_alias(scop, "CST_", "_CST");␊ |
␉␉␉}␊ |
␉␉␊ |
␉␉// Scope (\_PR) { Name (CST␊ |
␉␉writebyte(fd, 0x10); // id␊ |
␉␉if (name_length > 0x3f) ␊ |
␉␉{␊ |
␉␉␉writebyte(fd, 0x40 | (name_length & 0xf)); // lo half-byte␊ |
␉␉␉writebyte(fd, name_length >> 4); // hi byte␊ |
␉␉}␊ |
␉␉else ␊ |
␉␉{␊ |
␉␉␉writebyte(fd, name_length); // length␊ |
␉␉}␊ |
␉␉write(fd, chunk_name_body, sizeof(chunk_name_body));␊ |
␉␉aml_calculate_size(root);␊ |
␉␉␊ |
␉␉//Package (0x04) { 0x03,␊ |
␉␉writebyte(fd, 0x12); // id␊ |
␉␉if (package_length > 0x3f) ␊ |
␉␉{␊ |
␉␉␉writebyte(fd, 0x40 | (package_length & 0xf)); // lo half-byte␊ |
␉␉␉writebyte(fd, package_length >> 4); // hi byte␊ |
␉␉}␊ |
␉␉else ␊ |
␉␉{␊ |
␉␉␉writebyte(fd, package_length); // length␊ |
␉␉}␊ |
␉␉uint8_t cstates_count = 1 + c2_enabled + c3_enabled;␊ |
␉␉writebyte(fd, cstates_count + 1);␊ |
␉␉writebyte(fd, 0x0A); // first entry - number of c-states␊ |
␉␉writebyte(fd, cstates_count);␊ |
␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
␉␊ |
␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
␉␉␊ |
␉␉// C1␊ |
␉␉write(fd, chunk_c1, sizeof(chunk_c1));␊ |
␉␉␊ |
␉␉// C2␊ |
␉␉if (c2_enabled) ␊ |
␉␉␉write(fd, chunk_c2, sizeof(chunk_c2));␊ |
␉␉␊ |
␉␉// C3␊ |
␉␉if (c3_enabled) ␊ |
␉␉␉write(fd, chunk_c3, sizeof(chunk_c3));␊ |
␉␉␊ |
␉␉// Write aliases␊ |
␉␉int i;␊ |
␉␉for (i = 0; i < acpi_cpu_count; i++) {␊ |
␉␉␉int j;␊ |
␉␉␉for (j = 0; j < 4; j++)␊ |
␉␉␉␉chunk_alias[8+j] = acpi_cpu_name[i][j];␊ |
␉␉␉write(fd, chunk_alias, sizeof(chunk_alias));␊ |
␉␉}␊ |
␉␉␊ |
␉␉close(fd);␊ |
␉␉␊ |
␉␉ssdt->Length = ssdt_size;␊ |
␉␉ssdt->Length = root->Size;␊ |
␉␉ssdt->Checksum = 0;␊ |
␉␉ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);␊ |
␉␉␊ |
␉␉//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt_size);␊ |
␉␉aml_destroy_node(root);␊ |
␉␉␊ |
␉␉//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);␊ |
␉␉␉␉␊ |
␉␉verbose ("SSDT with CPU C-States generated successfully\n");␊ |
␉␉␊ |
␉␉return ssdt;␊ |
␉}␊ |
␉else {␊ |
␉␉verbose ("DSDT CPUs not found: C-States not generated !!!\n");␊ |
␉else ␊ |
␉{␊ |
␉␉verbose ("ACPI CPUs not found: C-States not generated !!!\n");␊ |
␉}␊ |
␊ |
␉return NULL;␊ |
|
␉␉0x31, 0x03, 0x10, 0x20,␉␉␉␉␉␉␉/* 1.._␉␉*/␊ |
␉};␊ |
␉␊ |
␉char chunk_name_body[] =␊ |
␉{␊ |
␉␉0x5C, 0x5F, 0x50, 0x52, 0x5F, 0x08, 0x50, 0x53, /* \_PR_.PS */␊ |
␉␉0x53, 0x5F␉␉␉␉␉␉␉␉␉␉/* S_␉␉*/␊ |
␉};␊ |
␉␊ |
␉char chunk_alias[] = ␊ |
␉{␊ |
␉␉0x10, 0x14, 0x5C, 0x2E, 0x5F, 0x50, 0x52, 0x5F, /* ..\._PR_ */␊ |
␉␉0x43, 0x50, 0x55, 0x30, 0x06, 0x50, 0x53, 0x53, /* CPU0.PSS */␊ |
␉␉0x5F, 0x5F, 0x50, 0x53, 0x53␉␉␉␉␉/* __PSS␉*/␊ |
␉};␊ |
␉␊ |
␉if (Platform.CPU.Vendor != 0x756E6547) {␊ |
␉␉verbose ("Not an Intel platform: P-States will not be generated !!!\n");␊ |
␉␉return NULL;␊ |
|
␉}␊ |
␉␊ |
␉if (acpi_cpu_count == 0) ␊ |
␉␉find_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
␉␊ |
␉if (acpi_cpu_count > 0) ␊ |
␉{␉␊ |
|
␉␉uint8_t p_states_count;␉␉␊ |
␉␉␊ |
␉␉// Retrieving P-States, ported from code by superhai (c)␊ |
␉␉␊ |
␊ |
␉␉␊ |
␉␉switch (Platform.CPU.Family) {␊ |
␉␉␉case 0x06: ␊ |
␉␉␉{␊ |
|
␉␉␉␉␉case 0x0F: // Intel Core (65nm)␊ |
␉␉␉␉␉case 0x17: // Intel Core (45nm)␊ |
␉␉␉␉␉case 0x1C: // Intel Atom (45nm)␊ |
␉␉␉␉␉case 0x1A: // Intel Core i7 LGA1366 (45nm)␊ |
␉␉␉␉␉case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)␊ |
␉␉␉␉␉case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)␊ |
␉␉␉␉␉case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core␊ |
␉␉␉␉␉␉if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27)) ␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); ␊ |
|
␉␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);␊ |
␉␉␉␉␉␉}␊ |
␉␉␉␉␉␉break;␊ |
␉␉␉␉␉case 0x1A: // Intel Core i7 LGA1366 (45nm)␊ |
␉␉␉␉␉case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)␊ |
␉␉␉␉␉case 0x1F:␊ |
␉␉␉␉␉case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)␊ |
␉␉␉␉␉case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core␊ |
␉␉␉␉␉case 0x2F:␊ |
␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 15);␊ |
␉␉␉␉␉␉break;␊ |
␉␉␉␉}␊ |
␉␉␉}␊ |
␉␉}␊ |
|
␉␉␊ |
␉␉if (minimum.FID == 0) ␊ |
␉␉{␊ |
␉␉␉uint64_t msr;␊ |
␉␉␉uint8_t i;␊ |
␉␉␉// Probe for lowest fid␊ |
␉␉␉for (i = maximum.FID; i >= 0x6; i--) ␊ |
␉␉␉{␊ |
␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
␉␉␉␉delay(1);␊ |
␉␉␉}␊ |
␉␉␉␊ |
␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉intel_waitforsts();␊ |
␉␉}␊ |
␉␉␊ |
␉␉if (minimum.VID == maximum.VID) ␊ |
␉␉{␉␊ |
␉␉␉uint64_t msr;␊ |
␉␉␉uint8_t i;␊ |
␉␉␉// Probe for lowest vid␊ |
␉␉␉for (i = maximum.VID; i > 0xA; i--) ␊ |
␉␉␉{␊ |
␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
␉␉␉␉intel_waitforsts();␊ |
␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
␉␉␉␉delay(1);␊ |
␉␉␉}␊ |
␉␉␉␊ |
␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
␉␉␉intel_waitforsts();␊ |
␉␉}␊ |
␉␉␊ |
|
␉␉␊ |
␉␉if (p_states_count > 0) ␊ |
␉␉{␉␊ |
␉␉␉uint32_t i, pss_entries_size = 33 * p_states_count, pss_package_length = pss_entries_size + 2;␊ |
␉␉␉int i;␊ |
␉␉␉␊ |
␉␉␉if (pss_package_length > 0x3f) pss_package_length++; // for chunks > 0x3f bytes length have 2 bytes encoding␊ |
␉␉␉struct aml_chunk* root = aml_create_node(NULL);␊ |
␉␉␉␉aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header␊ |
␉␉␉␉␉struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");␊ |
␉␉␉␉␉␉struct aml_chunk* name = aml_add_name(scop, "PSS_");␊ |
␉␉␉␉␉␉␉struct aml_chunk* pack = aml_add_package(name);␊ |
␉␉␉␊ |
␉␉␉uint32_t pss_name_length = (1 /* id=0x12 */ + pss_package_length) + (1 + 10);␊ |
␉␉␉␊ |
␉␉␉if (pss_name_length > 0x3f) pss_name_length++;␊ |
␉␉␉␊ |
␉␉␉uint32_t ssdt_size = 36 + (1 /* id=0x10 */ + pss_name_length) + acpi_cpu_count * sizeof(chunk_alias);␊ |
␉␉␉␊ |
␉␉␉struct acpi_2_ssdt *ssdt = (void*)AllocateKernelMemory(ssdt_size);␊ |
␉␉␉int fd = openmem((char*)ssdt, ssdt_size);␊ |
␉␉␉␊ |
␉␉␉// write header␊ |
␉␉␉write(fd, ssdt_header, sizeof(ssdt_header));␊ |
␉␉␉␊ |
␉␉␉// write Scope (\_PR) {␉Name (PSS, ...␊ |
␉␉␉writebyte(fd, 0x10); // id␊ |
␉␉␉if (pss_name_length > 0x3f) ␊ |
␉␉␉␉␉␉␉␉for (i = 0; i < p_states_count; i++) ␊ |
␉␉␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉␉␉struct aml_chunk* pstt = aml_add_package(pack);␊ |
␉␉␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, p_states[i].Frequency);␊ |
␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, 0x00000000); // Power␊ |
␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, p_states[i].Control);␊ |
␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, i+1); // Status␊ |
␉␉␉␉␉␉␉␉}␊ |
␉␉␉␉␊ |
␉␉␉// Add aliaces␊ |
␉␉␉for (i = 0; i < acpi_cpu_count; i++) ␊ |
␉␉␉{␊ |
␉␉␉␉writebyte(fd, 0x40 | (pss_name_length & 0xf)); // lo half-byte␊ |
␉␉␉␉writebyte(fd, pss_name_length >> 4); // hi byte␊ |
␉␉␉␉char name[9];␊ |
␉␉␉␉sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);␊ |
␉␉␉␉␊ |
␉␉␉␉scop = aml_add_scope(root, name);␊ |
␉␉␉␉aml_add_alias(scop, "PSS_", "_PSS");␊ |
␉␉␉}␊ |
␉␉␉else ␊ |
␉␉␉{␊ |
␉␉␉␉writebyte(fd, pss_name_length); // length␊ |
␉␉␉}␊ |
␉␉␉write(fd, chunk_name_body, sizeof(chunk_name_body));␊ |
␉␉␉␊ |
␉␉␉// write Package(p_states_count) { ...␊ |
␉␉␉writebyte(fd, 0x12); // id␊ |
␉␉␉if (pss_package_length > 0x3f) ␊ |
␉␉␉{␊ |
␉␉␉␉writebyte(fd, 0x40 | (pss_package_length & 0xf)); // lo half-byte␊ |
␉␉␉␉writebyte(fd, pss_package_length >> 4); // hi byte␊ |
␉␉␉}␊ |
␉␉␉else ␊ |
␉␉␉{␊ |
␉␉␉␉writebyte(fd, pss_package_length); // length␊ |
␉␉␉}␊ |
␉␉␉writebyte(fd, p_states_count); // entries␊ |
␉␉␉aml_calculate_size(root);␊ |
␉␉␉␊ |
␉␉␉for (i = 0; i < p_states_count; i++) ␊ |
␉␉␉{␊ |
␉␉␉␉DBG("P-State: Frequency %d MHz, FID 0x%x, VID 0x%x\n", p_states[i].Frequency, p_states[i].FID, p_states[i].VID);␊ |
␉␉␉␉␊ |
␉␉␉␉writebyte(fd, 0x12); // chunk id␊ |
␉␉␉␉writebyte(fd, 32); // chunk length without id ␊ |
␉␉␉␉writebyte(fd, 6); // entries␊ |
␉␉␉␉␊ |
␉␉␉␉writebyte(fd, 0x0C); /* id */ writeint(fd, p_states[i].Frequency); // value␊ |
␉␉␉␉writebyte(fd, 0x0C); /* id */ writeint(fd, 0x00000000); // value␊ |
␉␉␉␉writebyte(fd, 0x0C); /* id */ writeint(fd, 0x0000000A); // value␊ |
␉␉␉␉writebyte(fd, 0x0C); /* id */ writeint(fd, 0x0000000A); // value␊ |
␉␉␉␉writebyte(fd, 0x0C); /* id */ writeint(fd, p_states[i].Control); // value␊ |
␉␉␉␉writebyte(fd, 0x0C); /* id */ writeint(fd, i + 1); // value␊ |
␉␉␉}␊ |
␉␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
␉␉␉␊ |
␉␉␉// Write aliases␊ |
␉␉␉for (i = 0; i < acpi_cpu_count; i++) {␊ |
␉␉␉␉int j;␊ |
␉␉␉␉for (j = 0; j < 4; j++)␊ |
␉␉␉␉␉chunk_alias[8+j] = acpi_cpu_name[i][j];␊ |
␉␉␉␉write(fd, chunk_alias, sizeof(chunk_alias));␊ |
␉␉␉}␊ |
␉␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
␉␉␉␊ |
␉␉␉ssdt->Length = ssdt_size;␊ |
␉␉␉ssdt->Length = root->Size;␊ |
␉␉␉ssdt->Checksum = 0;␊ |
␉␉␉ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);␊ |
␉␉␉␊ |
␉␉␉//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt_size);␊ |
␉␉␉aml_destroy_node(root);␊ |
␉␉␉␊ |
␉␉␉//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);␊ |
␉␉␉␊ |
␉␉␉verbose ("SSDT with CPU P-States generated successfully\n");␊ |
␉␉␉␊ |
␉␉␉return ssdt;␊ |
␉␉}␊ |
␉}␊ |
␉else {␊ |
␉␉verbose ("DSDT CPUs not found: P-States not generated !!!\n");␊ |
␉␉verbose ("ACPI CPUs not found: P-States not generated !!!\n");␊ |
␉}␊ |
␉␊ |
␉return NULL;␊ |
|
␉␉else␊ |
␉␉␉Platform.Type = (unsigned char) strtoul(value, NULL, 10);␊ |
␉}␊ |
␉// Set PM_Profile from System-type if only if user wanted this value to be forced␊ |
␉// Set PM_Profile from System-type if only user wanted this value to be forced␊ |
␉if (fadt_mod->PM_Profile != Platform.Type) ␊ |
␉{␊ |
␉ if (value) ␊ |