[arch][x86][fpu] clean up the fpu init code to print info later
This commit is contained in:
123
arch/x86/fpu.c
123
arch/x86/fpu.c
@@ -37,67 +37,80 @@
|
||||
|
||||
/* CPUID EAX = 1 return values */
|
||||
|
||||
static int fp_supported;
|
||||
static bool fp_supported;
|
||||
static thread_t *fp_owner;
|
||||
|
||||
/* FXSAVE area comprises 512 bytes starting with 16-byte aligned */
|
||||
static uint8_t __ALIGNED(16) fpu_init_states[512]= {0};
|
||||
|
||||
void x86_fpu_early_init(void) {
|
||||
/* saved copy of some feature bits */
|
||||
typedef struct {
|
||||
bool with_fpu;
|
||||
bool with_sse;
|
||||
bool with_sse2;
|
||||
bool with_sse3;
|
||||
bool with_ssse3;
|
||||
bool with_sse4_1;
|
||||
bool with_sse4_2;
|
||||
bool with_sse4a;
|
||||
bool with_fxsave;
|
||||
bool with_xsave;
|
||||
|
||||
fp_supported = 0;
|
||||
bool with_xsaveopt;
|
||||
bool with_xsavec;
|
||||
bool with_xsaves;
|
||||
} fpu_features_t;
|
||||
|
||||
static fpu_features_t fpu_features;
|
||||
|
||||
/* called on the first cpu before the kernel is initialized. printfs may not work here */
|
||||
void x86_fpu_early_init(void) {
|
||||
fp_supported = false;
|
||||
fp_owner = NULL;
|
||||
|
||||
// test a bunch of fpu features
|
||||
const bool with_fpu = x86_feature_test(X86_FEATURE_FPU);
|
||||
const bool with_sse = x86_feature_test(X86_FEATURE_SSE);
|
||||
const bool with_sse2 = x86_feature_test(X86_FEATURE_SSE2);
|
||||
const bool with_sse3 = x86_feature_test(X86_FEATURE_SSE3);
|
||||
const bool with_ssse3 = x86_feature_test(X86_FEATURE_SSSE3);
|
||||
const bool with_sse4_1 = x86_feature_test(X86_FEATURE_SSE4_1);
|
||||
const bool with_sse4_2 = x86_feature_test(X86_FEATURE_SSE4_2);
|
||||
const bool with_sse4a = x86_feature_test(X86_FEATURE_SSE4A);
|
||||
const bool with_fxsave = x86_feature_test(X86_FEATURE_FXSR);
|
||||
const bool with_xsave = x86_feature_test(X86_FEATURE_XSAVE);
|
||||
|
||||
dprintf(SPEW, "X86: fpu %u sse %u sse2 %u sse3 %u ssse3 %u sse4.1 %u sse4.2 %u sse4a %u\n",
|
||||
with_fpu, with_sse, with_sse2, with_sse3, with_ssse3, with_sse4_1, with_sse4_2, with_sse4a);
|
||||
dprintf(SPEW, "X86: fxsave %u xsave %u\n", with_fxsave, with_xsave);
|
||||
fpu_features.with_fpu = x86_feature_test(X86_FEATURE_FPU);
|
||||
fpu_features.with_sse = x86_feature_test(X86_FEATURE_SSE);
|
||||
fpu_features.with_sse2 = x86_feature_test(X86_FEATURE_SSE2);
|
||||
fpu_features.with_sse3 = x86_feature_test(X86_FEATURE_SSE3);
|
||||
fpu_features.with_ssse3 = x86_feature_test(X86_FEATURE_SSSE3);
|
||||
fpu_features.with_sse4_1 = x86_feature_test(X86_FEATURE_SSE4_1);
|
||||
fpu_features.with_sse4_2 = x86_feature_test(X86_FEATURE_SSE4_2);
|
||||
fpu_features.with_sse4a = x86_feature_test(X86_FEATURE_SSE4A);
|
||||
fpu_features.with_fxsave = x86_feature_test(X86_FEATURE_FXSR);
|
||||
fpu_features.with_xsave = x86_feature_test(X86_FEATURE_XSAVE);
|
||||
|
||||
// these are the mandatory ones to continue (for the moment)
|
||||
if (!with_fpu || !with_sse || !with_fxsave) {
|
||||
dprintf(SPEW, "no usable FPU detected (requires SSE + FXSAVE)\n");
|
||||
if (!fpu_features.with_fpu || !fpu_features.with_sse || !fpu_features.with_fxsave) {
|
||||
return;
|
||||
}
|
||||
|
||||
fp_supported = 1;
|
||||
fp_supported = true;
|
||||
|
||||
dprintf(SPEW, "X86: SSE + FXSAVE detected\n");
|
||||
|
||||
// detect and print some xsave information
|
||||
// detect and save some xsave information
|
||||
// NOTE: currently unused
|
||||
bool with_xsaveopt = false;
|
||||
bool with_xsavec = false;
|
||||
bool with_xsaves = false;
|
||||
if (with_xsave) {
|
||||
fpu_features.with_xsaveopt = false;
|
||||
fpu_features.with_xsavec = false;
|
||||
fpu_features.with_xsaves = false;
|
||||
if (fpu_features.with_xsave) {
|
||||
dprintf(SPEW, "X86: XSAVE detected\n");
|
||||
struct x86_cpuid_leaf leaf;
|
||||
if (x86_get_cpuid_subleaf(X86_CPUID_XSAVE, 0, &leaf)) {
|
||||
with_xsaveopt = BIT(leaf.a, 0);
|
||||
with_xsavec = BIT(leaf.a, 1);
|
||||
with_xsaves = BIT(leaf.a, 3);
|
||||
dprintf(SPEW, "\txsaveopt %u xsavec %u xsaves %u\n", with_xsaveopt, with_xsavec, with_xsaves);
|
||||
dprintf(SPEW, "\txsave leaf 0: %#x %#x %#x %#x\n", leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
fpu_features.with_xsaveopt = BIT(leaf.a, 0);
|
||||
fpu_features.with_xsavec = BIT(leaf.a, 1);
|
||||
fpu_features.with_xsaves = BIT(leaf.a, 3);
|
||||
LTRACEF("xsaveopt %u xsavec %u xsaves %u\n", fpu_features.with_xsaveopt, fpu_features.with_xsavec, fpu_features.with_xsaves);
|
||||
LTRACEF("xsave leaf 0: %#x %#x %#x %#x\n", leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
}
|
||||
if (x86_get_cpuid_subleaf(X86_CPUID_XSAVE, 1, &leaf)) {
|
||||
dprintf(SPEW, "\txsave leaf 1: %#x %#x %#x %#x\n", leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
LTRACEF("xsave leaf 1: %#x %#x %#x %#x\n", leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
}
|
||||
|
||||
for (int i = 2; i < 64; i++) {
|
||||
if (x86_get_cpuid_subleaf(X86_CPUID_XSAVE, i, &leaf)) {
|
||||
if (leaf.a > 0) {
|
||||
dprintf(SPEW, "\txsave leaf %d: %#x %#x %#x %#x\n", i, leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
dprintf(SPEW, "\t\tstate %d: size required %u offset %u\n", i, leaf.a, leaf.b);
|
||||
LTRACEF("xsave leaf %d: %#x %#x %#x %#x\n", i, leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
LTRACEF("\tstate %d: size required %u offset %u\n", i, leaf.a, leaf.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,6 +163,42 @@ void x86_fpu_early_init(void) {
|
||||
}
|
||||
|
||||
void x86_fpu_init(void) {
|
||||
dprintf(SPEW, "X86: fpu %u sse %u sse2 %u sse3 %u ssse3 %u sse4.1 %u sse4.2 %u sse4a %u\n",
|
||||
fpu_features.with_fpu, fpu_features.with_sse, fpu_features.with_sse2,
|
||||
fpu_features.with_sse3, fpu_features.with_ssse3, fpu_features.with_sse4_1,
|
||||
fpu_features.with_sse4_2, fpu_features.with_sse4a);
|
||||
dprintf(SPEW, "X86: fxsave %u xsave %u\n", fpu_features.with_fxsave, fpu_features.with_xsave);
|
||||
|
||||
if (!fp_supported) {
|
||||
dprintf(SPEW, "no usable FPU detected (requires SSE + FXSAVE)\n");
|
||||
}
|
||||
|
||||
if (fpu_features.with_fxsave) {
|
||||
dprintf(SPEW, "X86: FXSAVE detected\n");
|
||||
}
|
||||
|
||||
if (fpu_features.with_xsave) {
|
||||
dprintf(SPEW, "X86: XSAVE detected\n");
|
||||
dprintf(SPEW, "\txsaveopt %u xsavec %u xsaves %u\n", fpu_features.with_xsaveopt, fpu_features.with_xsavec, fpu_features.with_xsaves);
|
||||
|
||||
struct x86_cpuid_leaf leaf;
|
||||
if (x86_get_cpuid_subleaf(X86_CPUID_XSAVE, 0, &leaf)) {
|
||||
dprintf(SPEW, "\txsave leaf 0: %#x %#x %#x %#x\n", leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
}
|
||||
if (x86_get_cpuid_subleaf(X86_CPUID_XSAVE, 1, &leaf)) {
|
||||
dprintf(SPEW, "\txsave leaf 1: %#x %#x %#x %#x\n", leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
}
|
||||
|
||||
for (int i = 2; i < 64; i++) {
|
||||
if (x86_get_cpuid_subleaf(X86_CPUID_XSAVE, i, &leaf)) {
|
||||
if (leaf.a > 0) {
|
||||
dprintf(SPEW, "\txsave leaf %d: %#x %#x %#x %#x\n", i, leaf.a, leaf.b, leaf.c, leaf.d);
|
||||
dprintf(SPEW, "\t\tstate %d: size required %u offset %u\n", i, leaf.a, leaf.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void fpu_init_thread_states(thread_t *t) {
|
||||
@@ -158,7 +207,7 @@ void fpu_init_thread_states(thread_t *t) {
|
||||
}
|
||||
|
||||
void fpu_context_switch(thread_t *old_thread, thread_t *new_thread) {
|
||||
if (fp_supported == 0)
|
||||
if (!fp_supported)
|
||||
return;
|
||||
|
||||
if (new_thread != fp_owner)
|
||||
@@ -174,7 +223,7 @@ void fpu_dev_na_handler(void) {
|
||||
|
||||
x86_set_cr0(x86_get_cr0() & ~X86_CR0_TS);
|
||||
|
||||
if (fp_supported == 0)
|
||||
if (!fp_supported)
|
||||
return;
|
||||
|
||||
self = get_current_thread();
|
||||
|
||||
Reference in New Issue
Block a user