[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freebsd-hackers
Subject:    Re: Floating point in interrupt handler
From:       "M. Warner Losh" <imp () bsdimp ! com>
Date:       2007-10-27 17:36:58
Message-ID: 20071027.113658.-2014464451.imp () bsdimp ! com
[Download RAW message or body]

In message: <200710271853.44167.Danovitsch@vitsch.net>
            "Daan Vreeken [PA4DAN]" <Danovitsch@vitsch.net> writes:
: Hi Warner,
: 
: On Wednesday 24 October 2007 23:15:13 you wrote:
: > In message: <200710222211.51590.Danovitsch@vitsch.net>
: >
: >             "Daan Vreeken [PA4DAN]" <Danovitsch@vitsch.net> writes:
: > : But what I haven't found is a description of exactly what the kernel is
: > : missing to allow floating point operations to be done there.
: >
: > FPU context is assumed to only change in user processes.  You'd have
: > to fix the FPU state saving code to cope with it changing everywhere,
: > or you'd have to explicitly put the goo to save/restore it around the
: > FP you want to do in the kernel.
:  
: Issei Suzuki pointed me into the right direction in his reply. (The following 
: text is an exact copy of the reply I sent to Issei, but I'll just copy it 
: here to show the code)
: If I understand the npx code correctly, there are 2 options when the kernel 
: arrives at hardclock() :
: o The current process is using the FPU (fpcurthread != NULL)
: o The current process hasn't used the FPU (yet) since it has been switched to
:    (fpcurthread == NULL)
: In the first case, FPU instructions can be used and will not result in a trap, 
: but we should save/restore the FPU state before using them so userland 
: doesn't get confused. In the last case FPU instructions result in a trap, so 
: we need stop/start_emulating(), but as no one is using the FPU, there is no 
: need to save/restore it's state.
: 
: With this in mind I've come up with the following code :
: 
: At the start of the function :
:         // check FPU state on entry
:         if (PCPU_GET(fpcurthread) != NULL) {
:                 // someone is using the FPU
:                 // save it's state and remember to put it back later
:                 restore = 1;
:                 fpusave(&fpu_state);
:         } else {
:                 // no one is using the FPU
:                 // enable use of FPU instructions, no need to save it's state
:                 restore = 0;
:                 stop_emulating();
:         }
:         // init FPU state every time we get here, as we don't know who has
:         // been playing with it in between calls
:         fninit();
:         control = __INITIAL_NPXCW__;
:         fldcw(&control);
: 
: Then we do some floating point arithmetic.
: 
: And at the end of the function :
:         // restore FPU state before we leave
:         if (restore) {
:                 // restore FPU registers to what they were
:                 fpurstor(&fpu_state);
:         } else {
:                 // no one was using the FPU, so re-enable the FPU trap
:                 start_emulating();
:         }
: 
: With this code trap-22 has stopped to trigger within my function. The FPU 
: instructions still seem to be executed correctly in my function and when 
: adding a couple of printf()'s I can see it fpusave() and fpurstor() when 
: interrupting a userland process that uses the FPU.
: Does this look reasonable to everyone?

My concern here would be to make sure that your code doesn't migrate
from one CPU to another.  Other than that, I think it is OK.

Warner
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic