hppa lazy FPU switching and QEMU bugs

Thor Lancelot Simon <[email protected]> Mon, 3 Aug 2026 22:57:54 -0400
Newsgroups gmane.os.netbsd.devel.crypto
Message-ID <[email protected]>
On Mon, Aug 03, 2026 at 03:59:18PM -0400, Thor Lancelot Simon wrote:
> 
> This host manages QEMU guests running the exact same version of NetBSD
> on 14 other emulated architectures.  Only hppa blows up like this.  I
> suppose some day someone will figure out why.

Actually the problem is not ML-KEM at all nor OpenSSL.  It's a bug in QEMU,
an information leak that can swap processes' FP registers!

An analysis generated using Claude:

  1. PA-RISC has no integer multiply instruction. GCC emits xmpyu, which
     executes in the FPU - verified in generated assembly, and it's true
     even for 32-bit unsigned int:                    
        mul32:  stws %r26,-16(%sp) ; fldws -16(%sp),%fr22R
                xmpyu %fr22R,%fr22L,%fr22       

  2. NetBSD/hppa uses lazy FPU switching. cpu_switchto (locore.S ~950)
     clears the CCR enable bits when switching to an LWP that isn't the
     current FP owner, and waits for assist-emulation trap 22 to swap FP state.

 3. QEMU defines EXCP_ASSIST_EMU in target/hppa/cpu.h:85 and never raises
    it, and never reads CR_CCR in translate.c.         

  4. So the swap never happens and every LWP shares the physical FP register
     file.                                    
                                         
I have a few different reproducers.  One is a fixed-input X25519 derivation in
the parent, versus a forked child doing nothing but z = z * 6364136223846793005ULL + 1:       
                                              
  idle        1200 derivations     0 wrong
  contended   1200 derivations   271 wrong   (22.6%)

Working on a simple way to detect this QEMU bug in our kernel and avoid
lazy FPU switching.  I won't commit any Claude-generated code, due to our
current policies, so it may take me a little while to ensure I understand
what it proposes and reimplement by hand.

Thor