--- a/sys/src/9/port/sysproc.c Wed Apr 8 17:18:17 2026 +++ b/sys/src/9/port/sysproc.c Wed Apr 8 17:21:11 2026 @@ -180,11 +180,6 @@ if((flag&RFNOTEG) == 0) p->noteid = up->noteid; - /* don't penalize the child, it hasn't done FP in a note handler. */ - if((up->fpstate>>FPnoteshift) != 0){ - fpoff(); - p->fpstate &= ~FPnotemask; - } pid = p->pid; memset(p->time, 0, sizeof(p->time)); p->time[TReal] = MACHP(0)->ticks; --- a/sys/src/9/bcm/dat.h Thu Mar 4 09:31:55 2021 +++ b/sys/src/9/bcm/dat.h Sun Mar 9 10:41:04 2025 @@ -83,6 +83,10 @@ /* * FPsave.fpstate + * + * FPinit: never used + * FPactive: in use, registers are live + * FPinactive: not in use, registers are saved */ enum { @@ -90,9 +94,11 @@ FPactive, FPinactive, FPemu, + FPnotestart, - /* bits or'd with the state */ - FPillegal= 0x100, + /* state repeated 3 bits up for note handler */ + FPnoteshift = 3, + FPnotemask = 7<<3, }; struct Confmem --- a/sys/src/9/bcm/fpiarm.c Thu Mar 10 15:07:05 2016 +++ b/sys/src/9/bcm/fpiarm.c Tue Jun 10 15:38:32 2025 @@ -475,8 +475,12 @@ ufp = &up->fpsave; /* * because all the emulated fp state is in the proc structure, - * it need not be saved/restored + * it need not be saved/restored except if fp is used in a note handler */ + if(up->fpstate & FPnotemask){ + /* in note handler */ + error("floating point in note handler"); + } switch(up->fpstate){ case FPactive: case FPinactive: --- a/sys/src/9/bcm/vfp3.c Wed May 20 12:59:36 2020 +++ b/sys/src/9/bcm/vfp3.c Thu Apr 2 10:11:08 2026 @@ -228,7 +228,7 @@ fpsave(&up->fpsave); up->fpstate = FPinactive; } - up->fpstate |= FPillegal; + up->fpstate |= FPnotestart<fpstate &= ~FPillegal; + if((up->fpstate>>FPnoteshift) == FPactive) + fpoff(); + up->fpstate &= ~FPnotemask; } /* @@ -254,7 +256,10 @@ if(up->fpstate == FPactive){ fpsave(&up->fpsave); up->fpstate = FPinactive; - } + }else if((up->fpstate>>FPnoteshift) == FPactive){ + fpsave(&up->notefpsave); + up->fpstate = (up->fpstate&~FPnotemask) | (FPinactive<fpstate = up->fpstate & ~FPillegal; + p->fpstate = up->fpstate; + /* no need to prevent child from using FP in note handler */ + if((p->fpstate>>FPnoteshift) != 0) + p->notefpsave = up->notefpsave; } /* should only be called if p->fpstate == FPactive */ @@ -281,13 +288,13 @@ } static void -fprestore(Proc *p) +fprestore(FPsave *fps) { fpon(); - fpwrscr(p->fpsave.control); + fpwrscr(fps->control); m->fpscr = fprdscr() & ~Allcc; assert(m->fpnregs); - fprestregs((uvlong*)p->fpsave.regs, m->fpnregs); + fprestregs((uvlong*)fps->regs, m->fpnregs); } /* @@ -300,7 +307,15 @@ void fpuprocsave(Proc *p) { - if(p->fpstate == FPactive){ + if(p->fpstate&FPnotemask){ + if((p->fpstate>>FPnoteshift) == FPactive){ + if(p->state == Moribund) + fpoff(); + else + fpsave(&p->notefpsave); + p->fpstate = (p->fpstate&~FPnotemask) | (FPinactive<fpstate == FPactive){ if(p->state == Moribund) fpoff(); else{ @@ -371,8 +386,36 @@ } static void -mathemu(Ureg *) +mathemu(Ureg*) { + if(up->fpstate & FPnotemask){ + /* in note handler */ + switch(up->fpstate>>FPnoteshift){ + case FPnotestart: + /* no FP used yet; copy state at time of note */ + if((up->fpstate&~FPnotemask) == FPinit) { + /* no FP in the process yet */ + up->fpstate = (up->fpstate&~FPnotemask) | (FPactive<notefpsave = up->fpsave; + /* fall through */ + case FPinactive: + /* restore state */ + if(up->fpsave.status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){ + postnote(up, 1, "sys: floating point exception in note handler", NDebug); + break; + } + fprestore(&up->notefpsave); + up->fpstate = (up->fpstate&~FPnotemask) | (FPactive<fpstate){ case FPemu: error("illegal instruction: VFP opcode in emulated mode"); @@ -392,7 +435,7 @@ mathnote(); break; } - fprestore(up); + fprestore(&up->fpsave); up->fpstate = FPactive; break; case FPactive: @@ -479,9 +522,6 @@ return 1; } - if(up->fpstate & FPillegal) - error("floating point in note handler"); - nfp = 0; pc = ureg->pc; validaddr(pc, 4, 0);