3

I was trying to add some asm code in ko module, simply:

asm volatile("vpush {d8}")

Error occurs while compiling:

Error: selected processor does not support ARM mode `vpush {d8}'

Is this expected? Thanks.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Bill Randerson
  • 1,028
  • 1
  • 11
  • 29

2 Answers2

3

Floating points are not used in kernel development in general. Not every hardware supports FP, some platforms may have advanced power features and can turn on and off FP unit at times. Handling all these is quite cumbersome and you can always find another way to solve your issue.

Robert Love's "Linux Kernel Development"

No (Easy) Use of Floating Point

... Using a floating point inside the kernel requires manually saving and restoring the floating point registers, among other possible chores. The short answer is: Don’t do it! Except in the rare cases, no floating-point operations are in the kernel.

And more... https://stackoverflow.com/a/13886805/1163019

It is that your compiler invocation doesn't specify any mfpu directives in compliance to above, so you get that error message.

Community
  • 1
  • 1
auselen
  • 27,577
  • 7
  • 73
  • 114
  • 2
    Note that kernel-mode NEON _is_ allowed provided support is compiled in (some of [the crypto modules](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/crypto) use it), but still has to be explicitly wrapped in `kernel_neon_begin()` and `kernel_neon_end()` (and those may be pretty expensive). – Notlikethat Apr 16 '15 at 09:05
  • @auselen, vpush is not a Floating Point operation, it's in effect a coprocessor operation, right? So does kernel doesn't allow operations on coprocessor? – Bill Randerson Apr 16 '15 at 11:01
  • @BillRanderson I think calling FPU as a coprocessor is too much of a generalization with later ARM architectures. Kernel of course allows coprocessor operations but `vpush {d8}` looks like a generic FP operation rather than some kernel house keeping. – auselen Apr 16 '15 at 11:16
  • @BillRanderson Floating-point operations _are_ coprocessor operations (the FPU is still conceptually a coprocessor) - the general considerations here indeed also apply to other implementation-defined coprocessors (e.g. iWMMX); they have to be powered up, access enabled, any current state saved, etc. – Notlikethat Apr 16 '15 at 11:16
  • @Notlikethat, I just want to do experiment in kernel to disable FPU by mcr and then issue an VFP instruction to see what will happen on my machine, would you guys give any recommendation how to do that? I though "mcr" can only be done in kernel, right? – Bill Randerson Apr 16 '15 at 11:20
  • @Bill Sure, if you're just having a play then simply stick an appropriate `.fpu ...` directive in the assembly to let it compile, then enjoy watching the machine go down in flames when it takes an undefined instruction exception in kernel mode - make sure your filesystem is synced first (or replaceable) ;) – Notlikethat Apr 16 '15 at 11:55
1

The main downside of kernel mode NEON (or vfp) is the register state must be saved/restored as a context switch can take place at any moment. So even if a co-processor is used, the challenge is to make any user visible state look the same when it runs. That is the Zeitgeist of this issue.

More recent kernels have Kconfig KERNEL_MODE_NEON inside Floating Point Emulation. The kernel mode NEON support is limited and documentation is found in Documentation/arm/kernel_mode_neon.txt. In order to make the kernel_neon_begin() and kernel_neon_end() register save/restores work, pre-emption is also disabled while they are in use; otherwise the scheduler would have to know that some kernel mode had change the NEON/VFP state and get it somewhere.

The KERNEL_MODE_NEON commit can be seen and it has restrictions for different GCC versions which can emit NEON code anywhere when compiled with -mpfu=neon; so any external call into the NEON compilation unit should be wrapped with kernel_neon_begin() and kernel_neon_end(). It should be present since 3.11 kernels.

artless noise
  • 21,212
  • 6
  • 68
  • 105