2002-02-14 00:11:57

by Rickard Westman

[permalink] [raw]
Subject: Using kernel_fpu_begin() in device driver - feasible or not?

Hi,

I am porting a device driver from an embedded platform where it's OK
to do floating-point arithmetic in drivers. To make it easy to
incorporate future improvements from this "reference driver", I have
tried to keep my modifications at a minimum, with most Linux-specific
code clearly separated. The heavy use of interspersed floating-point
arithmetic is an obstacle, though, as I'm aware of the policy to avoid
floating-point arithmetic in the Linux kernel.

Ideally, I'd like to use the FPU in a daemonized kernel thread created
by the driver, and possibly from process context as well (in the
implementation of some ioctl:s.) The target architecture is i386, and
non-portable solutions are quite acceptable.

Now, I've noticed that there are two interesting-looking functions in
the 2.4 kernel: kernel_fpu_begin() and kernel_fpu_end(). I have found
little information on how to use them, though, and I'd appreciate any
hints and guidelines. Here are some issues I'm concerned about:

1. Would it be sufficient to just bracket all fpu-using code code by
kernel_fpu_begin()/kernel_fpu_end()? If not, what problems could I
run into?

2. Would it be OK to go to sleep inside such a region, or should I
take care to avoid that?

3. Perhaps I should call init_fpu() at some point as well? If so,
should it be done before or after kernel_fpu_begin()?

4. Is there any difference between doing this in the context of a user
process (implementation of an ioctl) compared to doing it in a
daemonized kernel thread (created by a loadable kernel module)?

5. The functions mentioned above are not exported for use by loadable
modules, but I guess that could be arranged for. Is there any other
reason why it shouldn't work from a loadable kernel module?

Suggestions on alternative approaches are welcome as well, of course,
but I *do* realize that I could replace the calculations with
fixed-point arithmetic, divide things so that all floating-point
calculations were done in user-space, and similar ways to dodge the
issue. But for now, I'm just looking for feedback on how to actually
do it in kernel space, aesthetics aside...

--
Rickard Westman "Beware of the panacea peddlers: Just
<[email protected]> because you wind up naked doesn't
make you an emperor."
- Michael A Padlipsky


2002-02-14 13:33:51

by Alan

[permalink] [raw]
Subject: Re: Using kernel_fpu_begin() in device driver - feasible or not?

> 1. Would it be sufficient to just bracket all fpu-using code code by
> kernel_fpu_begin()/kernel_fpu_end()? If not, what problems could I
> run into?

You can do that providing you dont

> 2. Would it be OK to go to sleep inside such a region, or should I
> take care to avoid that?

You can't sleep in such a region - there is nowhere left to store the
FPU context

> 3. Perhaps I should call init_fpu() at some point as well? If so,
> should it be done before or after kernel_fpu_begin()?

After

> 4. Is there any difference between doing this in the context of a user
> process (implementation of an ioctl) compared to doing it in a
> daemonized kernel thread (created by a loadable kernel module)?

The kernel thread is actually easier, you can happily corrupt its user
FPU context by sleeping since you are the only FPU user for the thread.
Not nice, not portable but should work fine on x86 without any of the
above for the moment.

You should probably also test the FPU is present and handle it accordingly
with polite messages not an oops 8)

2002-02-14 14:04:42

by Alan

[permalink] [raw]
Subject: Re: Using kernel_fpu_begin() in device driver - feasible or not?

> > kernel_fpu_begin()/kernel_fpu_end()? If not, what problems could I
> > run into?
>
> You can do that providing you dont

Umm that wasn't me trying to be zen. I meant "you dont sleep"

2002-02-14 14:21:42

by Steffen Persvold

[permalink] [raw]
Subject: Re: Using kernel_fpu_begin() in device driver - feasible or not?

Alan Cox wrote:
>
> > 1. Would it be sufficient to just bracket all fpu-using code code by
> > kernel_fpu_begin()/kernel_fpu_end()? If not, what problems could I
> > run into?
>
> You can do that providing you dont
>
> > 2. Would it be OK to go to sleep inside such a region, or should I
> > take care to avoid that?
>
> You can't sleep in such a region - there is nowhere left to store the
> FPU context
>
> > 3. Perhaps I should call init_fpu() at some point as well? If so,
> > should it be done before or after kernel_fpu_begin()?
>
> After
>
> > 4. Is there any difference between doing this in the context of a user
> > process (implementation of an ioctl) compared to doing it in a
> > daemonized kernel thread (created by a loadable kernel module)?
>
> The kernel thread is actually easier, you can happily corrupt its user
> FPU context by sleeping since you are the only FPU user for the thread.
> Not nice, not portable but should work fine on x86 without any of the
> above for the moment.
>
> You should probably also test the FPU is present and handle it accordingly
> with polite messages not an oops 8)

So are kernel_fpu_begin()/kernel_fpu_end() (and also init_fpu()) necessary in a kernel thread at all
? Does kernel_fpu_begin()/kernel_fpu_end() take care of SSE and MMX registers too (I'm aware of the
extra "emms" needed in the MMX case) ?

Regards,
--
Steffen Persvold | Scalable Linux Systems | Try out the world's best
mailto:[email protected] | http://www.scali.com | performing MPI implementation:
Tel: (+47) 2262 8950 | Olaf Helsets vei 6 | - ScaMPI 1.13.8 -
Fax: (+47) 2262 8951 | N0621 Oslo, NORWAY | >320MBytes/s and <4uS latency