FPU problems
Posted: Sun Aug 15, 2010 9:12 pm
I recently discovered that my FPU code was broken (because my test code was being optimized out, and I haven't actually needed the FPU until now), but I can't seem to find the problem with it. I use CPUID to check for FXSAVE/FXRSTOR, FPU, and SSE support, which seems to indicate that the FPU exists, but the EM flag is set when the VM boots (indicating that it does not, IIRC), and clearing EM causes floating point exceptions with FPU use. All tests are being done in userspace. I'm using QEMU 0.12.4 with "-cpu qemu32" for testing, and I haven't done debugging of the FPU code on real boxes yet, although my OS does otherwise run fine on them.
Here is the key routine for FPU initialization (which sets the value of the dword at can_use_fpu, which is zero initially, according to its findings):
Does anyone see something immediately wrong with this routine? The problem may be elsewhere.
Here is the key routine for FPU initialization (which sets the value of the dword at can_use_fpu, which is zero initially, according to its findings):
Code: Select all
init_fpu:
push ebx
; check CPUID for FXSR bit
mov eax, 1
cpuid
test edx, 0x01000000
jne .nofx
; set OSFXSR bit in CR4
mov eax, cr4
or eax, 0x200
mov cr4, eax
mov eax, 1
mov [can_use_fpu], eax
; check CPUID for FPU bit
test edx, 0x00000001
jne .nofpu
; set FPU control word
.cw:
mov ax, 0x37F
mov [.cw], ax
fldcw [.cw]
.nofpu:
; check CPUID for SSE bit
test edx, 0x02000000
jne .nosse
; initialize SSE
mov eax, cr0
and eax, 0xFFFFFFFB
or eax, 0x2
mov cr0, eax
mov eax, cr4
or eax, 0x00000600
mov cr4, eax
.nosse:
.nofx:
pop ebx
ret