x86[_64]: Add support for CPUID sub-leaves

Some CPUID leaves may contain one or more sub-leaves accessed by setting
ECX to an appropriate value.
This commit is contained in:
Pawel Dziepak
2013-10-01 20:31:18 +02:00
parent c48c3f88a9
commit 4110b730db
10 changed files with 24 additions and 20 deletions
@@ -12,7 +12,7 @@
extern "C" { extern "C" {
#endif #endif
status_t get_current_cpuid(cpuid_info* info, uint32 eax); status_t get_current_cpuid(cpuid_info* info, uint32 eax, uint32 ecx);
uint32 get_eflags(void); uint32 get_eflags(void);
void set_eflags(uint32 value); void set_eflags(uint32 value);
+2 -2
View File
@@ -208,9 +208,9 @@ generic_mtrr_compute_physical_mask(void)
uint32 bits = 36; uint32 bits = 36;
cpuid_info cpuInfo; cpuid_info cpuInfo;
if (get_current_cpuid(&cpuInfo, 0x80000000) == B_OK if (get_current_cpuid(&cpuInfo, 0x80000000, 0) == B_OK
&& (cpuInfo.eax_0.max_eax & 0xff) >= 8) { && (cpuInfo.eax_0.max_eax & 0xff) >= 8) {
get_current_cpuid(&cpuInfo, 0x80000008); get_current_cpuid(&cpuInfo, 0x80000008, 0);
bits = cpuInfo.regs.eax & 0xff; bits = cpuInfo.regs.eax & 0xff;
// Obviously, the bits are not always reported correctly // Obviously, the bits are not always reported correctly
@@ -91,7 +91,7 @@ intel_cpuidle_init(void)
return B_ERROR; return B_ERROR;
cpuid_info cpuid; cpuid_info cpuid;
get_current_cpuid(&cpuid, 5); get_current_cpuid(&cpuid, 5, 0);
/* ecx[0] monitor/mwait extension supported /* ecx[0] monitor/mwait extension supported
* ecx[1] support for treating interrupts as break-events for mwait * ecx[1] support for treating interrupts as break-events for mwait
* edx number of sub-states * edx number of sub-states
+1 -1
View File
@@ -327,7 +327,7 @@ check_cpu_features()
} }
cpuid_info info; cpuid_info info;
if (get_current_cpuid(&info, 1) != B_OK) if (get_current_cpuid(&info, 1, 0) != B_OK)
return B_ERROR; return B_ERROR;
if ((info.eax_1.features & RDTSC_FEATURE) == 0) { if ((info.eax_1.features & RDTSC_FEATURE) == 0) {
+1 -1
View File
@@ -330,7 +330,7 @@ long_start_kernel()
{ {
// Check whether long mode is supported. // Check whether long mode is supported.
cpuid_info info; cpuid_info info;
get_current_cpuid(&info, 0x80000001); get_current_cpuid(&info, 0x80000001, 0);
if ((info.regs.edx & (1 << 29)) == 0) if ((info.regs.edx & (1 << 29)) == 0)
panic("64-bit kernel requires a 64-bit CPU"); panic("64-bit kernel requires a 64-bit CPU");
+2 -2
View File
@@ -581,7 +581,7 @@ smp_add_safemode_menus(Menu *menu)
item->SetHelpText("Disables using the local APIC, also disables SMP."); item->SetHelpText("Disables using the local APIC, also disables SMP.");
cpuid_info info; cpuid_info info;
if (get_current_cpuid(&info, 1) == B_OK if (get_current_cpuid(&info, 1, 0) == B_OK
&& (info.regs.ecx & IA32_FEATURE_EXT_X2APIC) != 0) { && (info.regs.ecx & IA32_FEATURE_EXT_X2APIC) != 0) {
#if 0 #if 0
menu->AddItem(item = new(nothrow) MenuItem("Disable X2APIC")); menu->AddItem(item = new(nothrow) MenuItem("Disable X2APIC"));
@@ -617,7 +617,7 @@ smp_init(void)
#endif #endif
cpuid_info info; cpuid_info info;
if (get_current_cpuid(&info, 1) != B_OK) if (get_current_cpuid(&info, 1, 0) != B_OK)
return; return;
if ((info.eax_1.features & IA32_FEATURE_APIC) == 0) { if ((info.eax_1.features & IA32_FEATURE_APIC) == 0) {
+3 -1
View File
@@ -11,12 +11,14 @@
.text .text
/* void get_current_cpuid(cpuid_info *info, uint32 eaxRegister) */ /* void get_current_cpuid(cpuid_info *info, uint32 eaxRegister,
uint32 ecxRegister) */
FUNCTION(get_current_cpuid): FUNCTION(get_current_cpuid):
pushl %ebx pushl %ebx
pushl %edi pushl %edi
movl 12(%esp),%edi /* first arg points to the cpuid_info structure */ movl 12(%esp),%edi /* first arg points to the cpuid_info structure */
movl 16(%esp),%eax /* second arg sets up eax */ movl 16(%esp),%eax /* second arg sets up eax */
movl 20(%esp),%ecx /* third arg sets up ecx */
cpuid cpuid
movl %eax,0(%edi) /* copy the regs into the cpuid_info structure */ movl %eax,0(%edi) /* copy the regs into the cpuid_info structure */
movl %ebx,4(%edi) movl %ebx,4(%edi)
+3 -1
View File
@@ -10,10 +10,12 @@
.text .text
/* status_t get_current_cpuid(cpuid_info* info, uint32 eaxRegister) */ /* status_t get_current_cpuid(cpuid_info* info, uint32 eaxRegister,
uint32 ecxRegister) */
FUNCTION(get_current_cpuid): FUNCTION(get_current_cpuid):
push %rbx push %rbx
movl %esi, %eax movl %esi, %eax
movl %edx, %ecx
cpuid cpuid
movl %eax, 0(%rdi) movl %eax, 0(%rdi)
movl %ebx, 4(%rdi) movl %ebx, 4(%rdi)
+9 -9
View File
@@ -522,7 +522,7 @@ detect_cpu(int currentCPU)
cpu->arch.model_name[0] = 0; cpu->arch.model_name[0] = 0;
// print some fun data // print some fun data
get_current_cpuid(&cpuid, 0); get_current_cpuid(&cpuid, 0, 0);
uint32 maxBasicLeaf = cpuid.eax_0.max_eax; uint32 maxBasicLeaf = cpuid.eax_0.max_eax;
// build the vendor string // build the vendor string
@@ -530,7 +530,7 @@ detect_cpu(int currentCPU)
memcpy(vendorString, cpuid.eax_0.vendor_id, sizeof(cpuid.eax_0.vendor_id)); memcpy(vendorString, cpuid.eax_0.vendor_id, sizeof(cpuid.eax_0.vendor_id));
// get the family, model, stepping // get the family, model, stepping
get_current_cpuid(&cpuid, 1); get_current_cpuid(&cpuid, 1, 0);
cpu->arch.type = cpuid.eax_1.type; cpu->arch.type = cpuid.eax_1.type;
cpu->arch.family = cpuid.eax_1.family; cpu->arch.family = cpuid.eax_1.family;
cpu->arch.extended_family = cpuid.eax_1.extended_family; cpu->arch.extended_family = cpuid.eax_1.extended_family;
@@ -561,27 +561,27 @@ detect_cpu(int currentCPU)
} }
// see if we can get the model name // see if we can get the model name
get_current_cpuid(&cpuid, 0x80000000); get_current_cpuid(&cpuid, 0x80000000, 0);
uint32 maxExtendedLeaf = cpuid.eax_0.max_eax; uint32 maxExtendedLeaf = cpuid.eax_0.max_eax;
if (maxExtendedLeaf >= 0x80000004) { if (maxExtendedLeaf >= 0x80000004) {
// build the model string (need to swap ecx/edx data before copying) // build the model string (need to swap ecx/edx data before copying)
unsigned int temp; unsigned int temp;
memset(cpu->arch.model_name, 0, sizeof(cpu->arch.model_name)); memset(cpu->arch.model_name, 0, sizeof(cpu->arch.model_name));
get_current_cpuid(&cpuid, 0x80000002); get_current_cpuid(&cpuid, 0x80000002, 0);
temp = cpuid.regs.edx; temp = cpuid.regs.edx;
cpuid.regs.edx = cpuid.regs.ecx; cpuid.regs.edx = cpuid.regs.ecx;
cpuid.regs.ecx = temp; cpuid.regs.ecx = temp;
memcpy(cpu->arch.model_name, cpuid.as_chars, sizeof(cpuid.as_chars)); memcpy(cpu->arch.model_name, cpuid.as_chars, sizeof(cpuid.as_chars));
get_current_cpuid(&cpuid, 0x80000003); get_current_cpuid(&cpuid, 0x80000003, 0);
temp = cpuid.regs.edx; temp = cpuid.regs.edx;
cpuid.regs.edx = cpuid.regs.ecx; cpuid.regs.edx = cpuid.regs.ecx;
cpuid.regs.ecx = temp; cpuid.regs.ecx = temp;
memcpy(cpu->arch.model_name + 16, cpuid.as_chars, memcpy(cpu->arch.model_name + 16, cpuid.as_chars,
sizeof(cpuid.as_chars)); sizeof(cpuid.as_chars));
get_current_cpuid(&cpuid, 0x80000004); get_current_cpuid(&cpuid, 0x80000004, 0);
temp = cpuid.regs.edx; temp = cpuid.regs.edx;
cpuid.regs.edx = cpuid.regs.ecx; cpuid.regs.edx = cpuid.regs.ecx;
cpuid.regs.ecx = temp; cpuid.regs.ecx = temp;
@@ -604,19 +604,19 @@ detect_cpu(int currentCPU)
} }
// load feature bits // load feature bits
get_current_cpuid(&cpuid, 1); get_current_cpuid(&cpuid, 1, 0);
cpu->arch.feature[FEATURE_COMMON] = cpuid.eax_1.features; // edx cpu->arch.feature[FEATURE_COMMON] = cpuid.eax_1.features; // edx
cpu->arch.feature[FEATURE_EXT] = cpuid.eax_1.extended_features; // ecx cpu->arch.feature[FEATURE_EXT] = cpuid.eax_1.extended_features; // ecx
if (maxExtendedLeaf >= 0x80000001) { if (maxExtendedLeaf >= 0x80000001) {
get_current_cpuid(&cpuid, 0x80000001); get_current_cpuid(&cpuid, 0x80000001, 0);
cpu->arch.feature[FEATURE_EXT_AMD] = cpuid.regs.edx; // edx cpu->arch.feature[FEATURE_EXT_AMD] = cpuid.regs.edx; // edx
if (cpu->arch.vendor != VENDOR_AMD) if (cpu->arch.vendor != VENDOR_AMD)
cpu->arch.feature[FEATURE_EXT_AMD] &= IA32_FEATURES_INTEL_EXT; cpu->arch.feature[FEATURE_EXT_AMD] &= IA32_FEATURES_INTEL_EXT;
} }
if (maxBasicLeaf >= 6) { if (maxBasicLeaf >= 6) {
get_current_cpuid(&cpuid, 6); get_current_cpuid(&cpuid, 6, 0);
cpu->arch.feature[FEATURE_6_EAX] = cpuid.regs.eax; cpu->arch.feature[FEATURE_6_EAX] = cpuid.regs.eax;
cpu->arch.feature[FEATURE_6_ECX] = cpuid.regs.ecx; cpu->arch.feature[FEATURE_6_ECX] = cpuid.regs.ecx;
} }
@@ -29,7 +29,7 @@ get_cpuid_for(cpuid_info *info, uint32 currentCPU, uint32 eaxRegister,
if (currentCPU != forCPU) if (currentCPU != forCPU)
return false; return false;
get_current_cpuid(info, eaxRegister); get_current_cpuid(info, eaxRegister, 0);
return true; return true;
} }