Messages in this thread |  | | From | rohrer keith w <> | Subject | Re: MMX for kernel | Date | Fri, 7 Feb 1997 11:59:41 -0600 (CST) |
| |
> The really important point (which I think Jason didn't understand) is > that the FPU registers *aren't* saved and restored across task > switches. The kernel plays a lazy evaluation game; there is a pointer > which points to the task which last used the FPU, and if the task that > is currently running isn't that task, the FPU is set to be > *invalidated*, which causes the i386 hardware to perform a fault to the > kernel when an FPU instruction is attempted. At that point, the kernel > saves the FPU registers for the old task, loads the FPU registers for > the currently running task, and restarts the instruction. [snip] > As a result, though, if the kernel wants to use the FPU registers, it > absolutely will have to save and then restore them, to avoid screwing up > the above scheme. Saving the old registers is necessary, assuming the last process to use the FPU is still alive (otherwise it's a no-op). However, a later restore should be already handled by the existing code, so long as we can pretend to be just another task...separate from our "user space persona", if any. That last might be the tricky part...
> Actually, what we could do is put in better logic to > determine whether or not the FPU is in use by a task (which is harder > than you think because crt0 does zero them out, so you have to filter > out that case), and then if the FPU isn't in use, you wouldn't need to > restore the FPU right away. Not "in use by a task", but "in use by this task" (or even "in use by this task in user space" if we let the compiler worry about nested usage of the FPU within the kernel). I assume that either this kernel-level FPU usage happens with interrupts off, or that it already handles the possibility of a context switch to and back from some other FPU-using process. To determine whether you want to restore the FPU registers immediately, before you start using the FPU you should check and see if the current task was the last FPU user. If it was, then you may as well restore the FPU registers when you finish, and leave the 387 valid (the current task should already still be the last user); if it was not, invalidate the FPU and set the last user to some flavor of "none", so that nothing bothers to save the garbage you'll never use again. A stricter test (useful in the case of multiple processes using the FPU lightly) would be to see if the current task was the last FPU user and the 387 is still valid (i.e. it used the FPU this timeslice); if so, you certainly want to restore the FPU immediately, and if not, you may wish to put off the restore.
> (You'd still have to do the lazy save, to > avoid losing the current FPU state.) True, assuming the current FPU state belongs to a live process.
In summary: see if we need to restore immediately by seeing if our user- level FPU usage was recent, and make sure we won't bother to save the dirty FPU registers once we're done with them (I'd hope this is done already...).
Keith
|  |