vmware and FPU in kernel

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

vmware and FPU in kernel

Post by proxy »

Hi all, long time reader (but rarely a poster).

A little background:
I have been developing a kernel for a while and have decided to put some effort into a video driver. My plan is for the driver itself to offer a few basic drawing primitives to allow for future hardware acceleration. The idea being that it will function a little like display lists where the user space app can queue up "draw rectangle(...); draw line(...); draw bitmap(...);" and then commit that to the video driver.

In addition to this I have a fairly complete, libc and libstdc++ for my kernel land. The libc is something on the order of 80-90% complete and as standards compliant as possible. This includes the FPU ops for example, cos/sin/tan all boil down to the correct x86 FPU instructions. I've tested in user space and they work nicely.

The question
Anyway, I have been attempting to implement the VESA based software version of this and have some good success so far...except for things involving the FPU ;).
Lines, Squares, Pixels, Bitmaps...all work fine, because they operate on squares. Circles are another story :).

I've been attempting to implement some circle drawing stuff which requires (at the least) a floating point division, sine and arccos. Unfortunately, vmware just locks up :(. I've tried debugging with bochs/qemu with confusing results. My test is I have a command which just does this in my kernel:

Code: Select all

    double d = sqrt(2.0);
    printf("%f\n", d);
vmware: locks up in the sqrt (a little "printf debugging" shows it doesn't seem to enter the sqrt function, so it seems it is dying on the FPU load ops before the call).
qemu: prints correct answer
bochs: prints nan.

Is there anything special I need to do to setup a sane FPU environment in kernel land? I do a fsave/frstor on task switch. And I do an finit early in my kernel's "main" function. What am I missing?
Last edited by proxy on Mon Apr 06, 2009 5:18 pm, edited 1 time in total.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: vmware and FPU in kernel

Post by Combuster »

first of all, you should be careful with sharing kernel FPU state. If you run FPU code in a separate kernel-only thread, then it should work as expected if you properly restore FPU state on switch, or with lazy FPU state switches.

If the kernel FPU state is not separate from other FPU states, then a lot can happen.

Since bochs is showing a bug as well, I suggest you try debugging there first.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: vmware and FPU in kernel

Post by proxy »

Agreed, I actually do a FPU save/restore on every switch (no lazy implementation yet). So the each kernel thread should have their own separate FPU state.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: vmware and FPU in kernel

Post by 01000101 »

You can check the wiki for the way to set the FPU environment up properly and allow for MMX/SSE to be used.

You need to ensure you have a good FPU control word setup, FINIT, and make sure you save the FPU/MMX/SSE context every interrupt (FXSAVE/FXRSTOR).
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: vmware and FPU in kernel

Post by proxy »

If I am only using regular FPU ops, do I need to save/restore MMX/SSE states too?
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: vmware and FPU in kernel

Post by 01000101 »

it saves the FPU state as well.
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: vmware and FPU in kernel

Post by proxy »

So I've looked at http://wiki.osdev.org/FPU and added it to my kernel, no effect. BTW, it has a bug in it, g++ 4.3.3 won't compile this like:

Code: Select all

        asm volatile("fldcw (%0);    "    // sets the FPU control word to "cw"
                     "fstcw (%1);    "    // store the FPU control word into FPU_CW
                     ::"r"(cw), "r"(&FPU_CW)); 
change it to

Code: Select all

        __asm__ __volatile__("fldcw %0;    "    // sets the FPU control word to "cw"
                     "fstcw (%1);    "    // store the FPU control word into FPU_CW
                     ::"m" (*&cw), "r"(&FPU_CW)); 
and it will compile fine. Though considering that I have no desire to use SSE at all, I think that is a bit overkill. I should be able to just finit during boot and fsave/fstor on context switch right?
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: vmware and FPU in kernel

Post by 01000101 »

what was the error?

And that code doesn't deal with SSE, the SSE page does. :wink:
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: vmware and FPU in kernel

Post by proxy »

the error was:
src/kernel.cpp:119: Error: `(%ax)' is not a valid base/index expression
src/kernel.cpp:119: Error: `(%ax)' is not a valid base/index expression
and like i said I am not using SSE at all So unless I am missing something I fail to see why that's a factor.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: vmware and FPU in kernel

Post by 01000101 »

ah, you could just specify "b" as the register to use instead of letting GCC pick the wrong register to use as a base index register. Thanks.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: vmware and FPU in kernel

Post by Brendan »

Hi,
proxy wrote:I should be able to just finit during boot and fsave/fstor on context switch right?
You'd also need to provide a clean FPU state for each task/thread spawned - either by doing a "finit" just after the new task starts running (before it can use the FPU), or by copying a "pre-initialized" FPU state from somewhere into the new task's FPU state save area before it starts running.

I'd also recommend setting the "NE" bit in CR0 to enable the native FPU error reporting (instead of routing FPU errors through IRQ13). Then you'd probably want some sort of FPU exception handler for any exceptions that any task could want to enable (all of them). Note: the default value for the FPU control word is for all the FPU exceptions to be enabled except for precision and underflow.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: vmware and FPU in kernel

Post by proxy »

Ahh, now that makes sense. I think that when a thread starts it's FPU state block is set to all zero's. In addition, I do my finit in what becomes the idle thread... my finit is all for naught!

I'll have to make my thread object copy the FPU state from the idle task's FPU state block. Maybe that'll fix it.

Thanks!
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: vmware and FPU in kernel

Post by proxy »

We have a winner!

Adding an finit to each task before they start executing the thread code worked like a charm in bochs/qemu/vmware :).

Thanks Brendan, as usual you are very helpful.
Post Reply