A single fix for GICv3 to not take an interrupt in an NMI context.

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmDO6X8ACgkQEsHwGGHe
 VUpz8hAAwaEfQmTDwJ+4PKOklmEdn7sgIeuIVXFrpCn1psDB0btqkrzAPkzPAM63
 ISnvKuySId3uDQ5mmgLwaQDsa3j1yciOhdyA3dGBCidtR6zcm/hCM48y3iUs1kRH
 CS8Ai/MpUQzi8Y/bFDMkQ3yedQG5CMApy63xk3MVlNh+jUBZkQ3fSPynrVN+jVR0
 nBbJXkKcMD7CGFgQnNO7weqnYJrcxWuQZSHALotJDBoVas0sgj97CLDDLmA5n8NW
 42QLW7OUxEUkMfRWb/iCqkzZ7vrKVUHZC2d/rBzWCRIQy5SHIwwVg4FFeAr51cTt
 72+MTf6lnA8aXQffVyvMPnHuhSp1ynin5NOMsu3YXMbF1lIU8ptKy5V3ttvF+Bcb
 cktI5i076PjScbvxbikTrI0QmLoeb2QTEnDgErrUN7CZLcVZQFLXtYbjrQvI9ycF
 8Ezw3a76tIzb4uSaxar8e4Sn1lc8VpEDUMNlhAu1/g/mFzlHF86QLuh4y4mjrReV
 9P1hMqtlfbDvLpQVu8S6KlrwXv+znqpRg9utA6SgJzt6yjnywOzlcptIdjHg3fE2
 gxhGs7/edp3NkN936o5Bh5vydtrCGUMtAS2KcxuRXKyEdusOgYJUgo85/QX2mI1h
 xNzn1yVjQuvU/Hp91nM7V/9boeDYgGqzRCQKR9frVTDHilezn9Q=
 =Ss4I
 -----END PGP SIGNATURE-----

Merge tag 'irq_urgent_for_v5.13_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fix from Borislav Petkov:
 "A single fix for GICv3 to not take an interrupt in an NMI context"

* tag 'irq_urgent_for_v5.13_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irqchip/gic-v3: Workaround inconsistent PMR setting on NMI entry
This commit is contained in:
Linus Torvalds 2021-06-20 09:38:14 -07:00
commit 9df7f15ee9
1 changed files with 35 additions and 1 deletions

View File

@ -642,11 +642,45 @@ static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs)
nmi_exit();
}
static u32 do_read_iar(struct pt_regs *regs)
{
u32 iar;
if (gic_supports_nmi() && unlikely(!interrupts_enabled(regs))) {
u64 pmr;
/*
* We were in a context with IRQs disabled. However, the
* entry code has set PMR to a value that allows any
* interrupt to be acknowledged, and not just NMIs. This can
* lead to surprising effects if the NMI has been retired in
* the meantime, and that there is an IRQ pending. The IRQ
* would then be taken in NMI context, something that nobody
* wants to debug twice.
*
* Until we sort this, drop PMR again to a level that will
* actually only allow NMIs before reading IAR, and then
* restore it to what it was.
*/
pmr = gic_read_pmr();
gic_pmr_mask_irqs();
isb();
iar = gic_read_iar();
gic_write_pmr(pmr);
} else {
iar = gic_read_iar();
}
return iar;
}
static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{
u32 irqnr;
irqnr = gic_read_iar();
irqnr = do_read_iar(regs);
/* Check for special IDs first */
if ((irqnr >= 1020 && irqnr <= 1023))