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
Unified · Split
| @@ -642,11 +642,45 @@ static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs) · 641 unmodified lines | ||
| 642 | 642 | nmi_exit(); |
| 643 | 643 | } |
| 644 | 644 | |
| 645 | +static u32 do_read_iar(struct pt_regs *regs) | |
| 646 | +{ | |
| 647 | + u32 iar; | |
| 648 | + | |
| 649 | + if (gic_supports_nmi() && unlikely(!interrupts_enabled(regs))) { | |
| 650 | + u64 pmr; | |
| 651 | + | |
| 652 | + /* | |
| 653 | + * We were in a context with IRQs disabled. However, the | |
| 654 | + * entry code has set PMR to a value that allows any | |
| 655 | + * interrupt to be acknowledged, and not just NMIs. This can | |
| 656 | + * lead to surprising effects if the NMI has been retired in | |
| 657 | + * the meantime, and that there is an IRQ pending. The IRQ | |
| 658 | + * would then be taken in NMI context, something that nobody | |
| 659 | + * wants to debug twice. | |
| 660 | + * | |
| 661 | + * Until we sort this, drop PMR again to a level that will | |
| 662 | + * actually only allow NMIs before reading IAR, and then | |
| 663 | + * restore it to what it was. | |
| 664 | + */ | |
| 665 | + pmr = gic_read_pmr(); | |
| 666 | + gic_pmr_mask_irqs(); | |
| 667 | + isb(); | |
| 668 | + | |
| 669 | + iar = gic_read_iar(); | |
| 670 | + | |
| 671 | + gic_write_pmr(pmr); | |
| 672 | + } else { | |
| 673 | + iar = gic_read_iar(); | |
| 674 | + } | |
| 675 | + | |
| 676 | + return iar; | |
| 677 | +} | |
| 678 | + | |
| 645 | 679 | static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) |
| 646 | 680 | { |
| 647 | 681 | u32 irqnr; |
| 648 | 682 | |
| 649 | − irqnr = gic_read_iar(); | |
| 683 | + irqnr = do_read_iar(regs); | |
| 650 | 684 | |
| 651 | 685 | /* Check for special IDs first */ |
| 652 | 686 | if ((irqnr >= 1020 && irqnr <= 1023)) |