Commit 3d306270 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Andrei Vagin

x86: cpu -- Sync bits with kernel

Tracking cpuid features is easier when sync'ed with kernel
source code. Note though that while in kernel feature bits
are not part of ABI, we're saving bits into an image so
as result make sure they are posted in proper place together
with keeping in mind the backward compatibility issue.

Here we also start using v2 of cpuinfo image with more
feature bits.
Reviewed-by: 's avatarDmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 380df8a6
......@@ -34,6 +34,8 @@ int compel_test_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
int compel_cpuid(compel_cpuinfo_t *c)
{
uint32_t eax, ebx, ecx, edx;
/*
* See cpu_detect() in the kernel, also
* read cpuid specs not only from general
......@@ -62,8 +64,6 @@ int compel_cpuid(compel_cpuinfo_t *c)
/* Intel-defined flags: level 0x00000001 */
if (c->cpuid_level >= 0x00000001) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
c->x86_family = (eax >> 8) & 0xf;
c->x86_model = (eax >> 4) & 0xf;
......@@ -74,34 +74,51 @@ int compel_cpuid(compel_cpuinfo_t *c)
if (c->x86_family >= 0x6)
c->x86_model += ((eax >> 16) & 0xf) << 4;
c->x86_capability[0] = edx;
c->x86_capability[4] = ecx;
c->x86_capability[CPUID_1_EDX] = edx;
c->x86_capability[CPUID_1_ECX] = ecx;
}
/* Thermal and Power Management Leaf: level 0x00000006 (eax) */
if (c->cpuid_level >= 0x00000006)
c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006);
/* Additional Intel-defined flags: level 0x00000007 */
if (c->cpuid_level >= 0x00000007) {
uint32_t eax, ebx, ecx, edx;
cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
c->x86_capability[9] = ebx;
c->x86_capability[11] = ecx;
c->x86_capability[CPUID_7_0_EBX] = ebx;
c->x86_capability[CPUID_7_0_ECX] = ecx;
c->x86_capability[CPUID_7_0_EDX] = edx;
}
/* Extended state features: level 0x0000000d */
if (c->cpuid_level >= 0x0000000d) {
uint32_t eax, ebx, ecx, edx;
cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
c->x86_capability[10] = eax;
c->x86_capability[CPUID_D_1_EAX] = eax;
}
/* Additional Intel-defined flags: level 0x0000000F */
if (c->cpuid_level >= 0x0000000F) {
/* QoS sub-leaf, EAX=0Fh, ECX=0 */
cpuid_count(0x0000000F, 0, &eax, &ebx, &ecx, &edx);
c->x86_capability[CPUID_F_0_EDX] = edx;
if (compel_test_cpu_cap(c, X86_FEATURE_CQM_LLC)) {
/* QoS sub-leaf, EAX=0Fh, ECX=1 */
cpuid_count(0x0000000F, 1, &eax, &ebx, &ecx, &edx);
c->x86_capability[CPUID_F_1_EDX] = edx;
}
}
/* AMD-defined flags: level 0x80000001 */
c->extended_cpuid_level = cpuid_eax(0x80000000);
eax = cpuid_eax(0x80000000);
c->extended_cpuid_level = eax;
if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000) {
if (c->extended_cpuid_level >= 0x80000001) {
c->x86_capability[1] = cpuid_edx(0x80000001);
c->x86_capability[6] = cpuid_ecx(0x80000001);
if ((eax & 0xffff0000) == 0x80000000) {
if (eax >= 0x80000001) {
cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
c->x86_capability[CPUID_8000_0001_ECX] = ecx;
c->x86_capability[CPUID_8000_0001_EDX] = edx;
}
}
......@@ -109,6 +126,9 @@ int compel_cpuid(compel_cpuinfo_t *c)
* We're don't care about scattered features for now,
* otherwise look into init_scattered_cpuid_features()
* in kernel.
*
* Same applies to speculation control. Look into
* init_speculation_control() otherwise.
*/
if (c->extended_cpuid_level >= 0x80000004) {
......@@ -135,9 +155,39 @@ int compel_cpuid(compel_cpuinfo_t *c)
}
}
if (c->extended_cpuid_level >= 0x80000007) {
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
c->x86_capability[CPUID_8000_0007_EBX] = ebx;
c->x86_power = edx;
}
if (c->extended_cpuid_level >= 0x8000000a)
c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
if (c->extended_cpuid_level >= 0x80000008)
c->x86_capability[CPUID_8000_0008_EBX] = cpuid_ebx(0x80000008);
/* On x86-64 CPUID is always present */
compel_set_cpu_cap(c, X86_FEATURE_CPUID);
/* On x86-64 NOP is always present */
compel_set_cpu_cap(c, X86_FEATURE_NOPL);
/*
* On x86-64 syscalls32 are enabled but we don't
* set it yet for backward compatibility reason
*/
//compel_set_cpu_cap(c, X86_FEATURE_SYSCALL32);
/* See filter_cpuid_features in kernel */
if ((int32_t)c->cpuid_level < (int32_t)0x0000000d)
compel_clear_cpu_cap(c, X86_FEATURE_XSAVE);
/*
* We only care about small subset from c_early_init:
* early_init_amd and early_init_intel
*/
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
/*
......@@ -152,9 +202,6 @@ int compel_cpuid(compel_cpuinfo_t *c)
compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
}
/* See filter_cpuid_features in kernel */
if ((int32_t)c->cpuid_level < (int32_t)0x0000000d)
compel_clear_cpu_cap(c, X86_FEATURE_XSAVE);
break;
case X86_VENDOR_AMD:
/*
......
......@@ -40,6 +40,14 @@ static inline unsigned int cpuid_eax(unsigned int op)
return eax;
}
static inline unsigned int cpuid_ebx(unsigned int op)
{
unsigned int eax, ebx, ecx, edx;
cpuid(op, &eax, &ebx, &ecx, &edx);
return ebx;
}
static inline unsigned int cpuid_ecx(unsigned int op)
{
unsigned int eax, ebx, ecx, edx;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment