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:
@@ -12,7 +12,7 @@
|
||||
extern "C" {
|
||||
#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);
|
||||
void set_eflags(uint32 value);
|
||||
|
||||
|
||||
@@ -208,9 +208,9 @@ generic_mtrr_compute_physical_mask(void)
|
||||
uint32 bits = 36;
|
||||
|
||||
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) {
|
||||
get_current_cpuid(&cpuInfo, 0x80000008);
|
||||
get_current_cpuid(&cpuInfo, 0x80000008, 0);
|
||||
bits = cpuInfo.regs.eax & 0xff;
|
||||
|
||||
// Obviously, the bits are not always reported correctly
|
||||
|
||||
@@ -91,7 +91,7 @@ intel_cpuidle_init(void)
|
||||
return B_ERROR;
|
||||
|
||||
cpuid_info cpuid;
|
||||
get_current_cpuid(&cpuid, 5);
|
||||
get_current_cpuid(&cpuid, 5, 0);
|
||||
/* ecx[0] monitor/mwait extension supported
|
||||
* ecx[1] support for treating interrupts as break-events for mwait
|
||||
* edx number of sub-states
|
||||
|
||||
@@ -327,7 +327,7 @@ check_cpu_features()
|
||||
}
|
||||
|
||||
cpuid_info info;
|
||||
if (get_current_cpuid(&info, 1) != B_OK)
|
||||
if (get_current_cpuid(&info, 1, 0) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if ((info.eax_1.features & RDTSC_FEATURE) == 0) {
|
||||
|
||||
@@ -330,7 +330,7 @@ long_start_kernel()
|
||||
{
|
||||
// Check whether long mode is supported.
|
||||
cpuid_info info;
|
||||
get_current_cpuid(&info, 0x80000001);
|
||||
get_current_cpuid(&info, 0x80000001, 0);
|
||||
if ((info.regs.edx & (1 << 29)) == 0)
|
||||
panic("64-bit kernel requires a 64-bit CPU");
|
||||
|
||||
|
||||
@@ -581,7 +581,7 @@ smp_add_safemode_menus(Menu *menu)
|
||||
item->SetHelpText("Disables using the local APIC, also disables SMP.");
|
||||
|
||||
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) {
|
||||
#if 0
|
||||
menu->AddItem(item = new(nothrow) MenuItem("Disable X2APIC"));
|
||||
@@ -617,7 +617,7 @@ smp_init(void)
|
||||
#endif
|
||||
|
||||
cpuid_info info;
|
||||
if (get_current_cpuid(&info, 1) != B_OK)
|
||||
if (get_current_cpuid(&info, 1, 0) != B_OK)
|
||||
return;
|
||||
|
||||
if ((info.eax_1.features & IA32_FEATURE_APIC) == 0) {
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
|
||||
.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):
|
||||
pushl %ebx
|
||||
pushl %edi
|
||||
movl 12(%esp),%edi /* first arg points to the cpuid_info structure */
|
||||
movl 16(%esp),%eax /* second arg sets up eax */
|
||||
movl 20(%esp),%ecx /* third arg sets up ecx */
|
||||
cpuid
|
||||
movl %eax,0(%edi) /* copy the regs into the cpuid_info structure */
|
||||
movl %ebx,4(%edi)
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
.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):
|
||||
push %rbx
|
||||
movl %esi, %eax
|
||||
movl %edx, %ecx
|
||||
cpuid
|
||||
movl %eax, 0(%rdi)
|
||||
movl %ebx, 4(%rdi)
|
||||
|
||||
@@ -522,7 +522,7 @@ detect_cpu(int currentCPU)
|
||||
cpu->arch.model_name[0] = 0;
|
||||
|
||||
// print some fun data
|
||||
get_current_cpuid(&cpuid, 0);
|
||||
get_current_cpuid(&cpuid, 0, 0);
|
||||
uint32 maxBasicLeaf = cpuid.eax_0.max_eax;
|
||||
|
||||
// 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));
|
||||
|
||||
// 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.family = cpuid.eax_1.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
|
||||
get_current_cpuid(&cpuid, 0x80000000);
|
||||
get_current_cpuid(&cpuid, 0x80000000, 0);
|
||||
uint32 maxExtendedLeaf = cpuid.eax_0.max_eax;
|
||||
if (maxExtendedLeaf >= 0x80000004) {
|
||||
// build the model string (need to swap ecx/edx data before copying)
|
||||
unsigned int temp;
|
||||
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;
|
||||
cpuid.regs.edx = cpuid.regs.ecx;
|
||||
cpuid.regs.ecx = temp;
|
||||
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;
|
||||
cpuid.regs.edx = cpuid.regs.ecx;
|
||||
cpuid.regs.ecx = temp;
|
||||
memcpy(cpu->arch.model_name + 16, cpuid.as_chars,
|
||||
sizeof(cpuid.as_chars));
|
||||
|
||||
get_current_cpuid(&cpuid, 0x80000004);
|
||||
get_current_cpuid(&cpuid, 0x80000004, 0);
|
||||
temp = cpuid.regs.edx;
|
||||
cpuid.regs.edx = cpuid.regs.ecx;
|
||||
cpuid.regs.ecx = temp;
|
||||
@@ -604,19 +604,19 @@ detect_cpu(int currentCPU)
|
||||
}
|
||||
|
||||
// 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_EXT] = cpuid.eax_1.extended_features; // ecx
|
||||
|
||||
if (maxExtendedLeaf >= 0x80000001) {
|
||||
get_current_cpuid(&cpuid, 0x80000001);
|
||||
get_current_cpuid(&cpuid, 0x80000001, 0);
|
||||
cpu->arch.feature[FEATURE_EXT_AMD] = cpuid.regs.edx; // edx
|
||||
if (cpu->arch.vendor != VENDOR_AMD)
|
||||
cpu->arch.feature[FEATURE_EXT_AMD] &= IA32_FEATURES_INTEL_EXT;
|
||||
}
|
||||
|
||||
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_ECX] = cpuid.regs.ecx;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ get_cpuid_for(cpuid_info *info, uint32 currentCPU, uint32 eaxRegister,
|
||||
if (currentCPU != forCPU)
|
||||
return false;
|
||||
|
||||
get_current_cpuid(info, eaxRegister);
|
||||
get_current_cpuid(info, eaxRegister, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user