Skip to content

Commit c0b5195

Browse files
Sebastian Andrzej SiewiorRussell King (Oracle)
authored andcommitted
ARM: 9426/1: vfp: Move sending signals outside of vfp_state_hold()ed section.
VFP_bounce() is invoked from within vfp_support_entry() and may send a signal. Sending a signal uses spinlock_t which becomes a sleeping lock on PREEMPT_RT and must not be acquired within a preempt-disabled section. Move the vfp_raise_sigfpe() block outside of the vfp_state_hold() section. Reviewed-by: Ard Biesheuvel <[email protected]> Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Russell King (Oracle) <[email protected]>
1 parent 27035c2 commit c0b5195

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

arch/arm/vfp/vfpmodule.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,16 +268,15 @@ static void vfp_panic(char *reason, u32 inst)
268268
/*
269269
* Process bitmask of exception conditions.
270270
*/
271-
static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
271+
static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr)
272272
{
273273
int si_code = 0;
274274

275275
pr_debug("VFP: raising exceptions %08x\n", exceptions);
276276

277277
if (exceptions == VFP_EXCEPTION_ERROR) {
278278
vfp_panic("unhandled bounce", inst);
279-
vfp_raise_sigfpe(FPE_FLTINV, regs);
280-
return;
279+
return FPE_FLTINV;
281280
}
282281

283282
/*
@@ -305,8 +304,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
305304
RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
306305
RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
307306

308-
if (si_code)
309-
vfp_raise_sigfpe(si_code, regs);
307+
return si_code;
310308
}
311309

312310
/*
@@ -352,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
352350
static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
353351
{
354352
u32 fpscr, orig_fpscr, fpsid, exceptions;
353+
int si_code2 = 0;
354+
int si_code = 0;
355355

356356
pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
357357

@@ -397,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
397397
* unallocated VFP instruction but with FPSCR.IXE set and not
398398
* on VFP subarch 1.
399399
*/
400-
vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
401-
return;
400+
si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr);
401+
goto exit;
402402
}
403403

404404
/*
@@ -422,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
422422
*/
423423
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
424424
if (exceptions)
425-
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
425+
si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
426426

427427
/*
428428
* If there isn't a second FP instruction, exit now. Note that
429429
* the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
430430
*/
431431
if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
432-
return;
432+
goto exit;
433433

434434
/*
435435
* The barrier() here prevents fpinst2 being read
@@ -441,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
441441
emulate:
442442
exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
443443
if (exceptions)
444-
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
444+
si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
445+
exit:
446+
vfp_state_release();
447+
if (si_code2)
448+
vfp_raise_sigfpe(si_code2, regs);
449+
if (si_code)
450+
vfp_raise_sigfpe(si_code, regs);
445451
}
446452

447453
static void vfp_enable(void *unused)
@@ -773,6 +779,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
773779
* replay the instruction that trapped.
774780
*/
775781
fmxr(FPEXC, fpexc);
782+
vfp_state_release();
776783
} else {
777784
/* Check for synchronous or asynchronous exceptions */
778785
if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
@@ -794,10 +801,10 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
794801
}
795802
}
796803
bounce: regs->ARM_pc += 4;
804+
/* VFP_bounce() will invoke vfp_state_release() */
797805
VFP_bounce(trigger, fpexc, regs);
798806
}
799807

800-
vfp_state_release();
801808
return 0;
802809
}
803810

0 commit comments

Comments
 (0)