···12121313/*1414 * Aarch64 has flags for masking: Debug, Asynchronous (serror), Interrupts and1515- * FIQ exceptions, in the 'daif' register. We mask and unmask them in 'dai'1515+ * FIQ exceptions, in the 'daif' register. We mask and unmask them in 'daif'1616 * order:1717 * Masking debug exceptions causes all other exceptions to be masked too/1818- * Masking SError masks irq, but not debug exceptions. Masking irqs has no1919- * side effects for other flags. Keeping to this order makes it easier for2020- * entry.S to know which exceptions should be unmasked.2121- *2222- * FIQ is never expected, but we mask it when we disable debug exceptions, and2323- * unmask it at all other times.1818+ * Masking SError masks IRQ/FIQ, but not debug exceptions. IRQ and FIQ are1919+ * always masked and unmasked together, and have no side effects for other2020+ * flags. Keeping to this order makes it easier for entry.S to know which2121+ * exceptions should be unmasked.2422 */25232624/*···3335 }34363537 asm volatile(ALTERNATIVE(3636- "msr daifclr, #2 // arch_local_irq_enable",3838+ "msr daifclr, #3 // arch_local_irq_enable",3739 __msr_s(SYS_ICC_PMR_EL1, "%0"),3840 ARM64_HAS_IRQ_PRIO_MASKING)3941 :···5254 }53555456 asm volatile(ALTERNATIVE(5555- "msr daifset, #2 // arch_local_irq_disable",5757+ "msr daifset, #3 // arch_local_irq_disable",5658 __msr_s(SYS_ICC_PMR_EL1, "%0"),5759 ARM64_HAS_IRQ_PRIO_MASKING)5860 :
+67-47
arch/arm64/kernel/entry.S
···491491/*492492 * Interrupt handling.493493 */494494- .macro irq_handler495495- ldr_l x1, handle_arch_irq494494+ .macro irq_handler, handler:req495495+ ldr_l x1, \handler496496 mov x0, sp497497 irq_stack_entry498498 blr x1···531531#endif532532 .endm533533534534+ .macro el1_interrupt_handler, handler:req535535+ gic_prio_irq_setup pmr=x20, tmp=x1536536+ enable_da537537+538538+ mov x0, sp539539+ bl enter_el1_irq_or_nmi540540+541541+ irq_handler \handler542542+543543+#ifdef CONFIG_PREEMPTION544544+ ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count545545+alternative_if ARM64_HAS_IRQ_PRIO_MASKING546546+ /*547547+ * DA were cleared at start of handling, and IF are cleared by548548+ * the GIC irqchip driver using gic_arch_enable_irqs() for549549+ * normal IRQs. If anything is set, it means we come back from550550+ * an NMI instead of a normal IRQ, so skip preemption551551+ */552552+ mrs x0, daif553553+ orr x24, x24, x0554554+alternative_else_nop_endif555555+ cbnz x24, 1f // preempt count != 0 || NMI return path556556+ bl arm64_preempt_schedule_irq // irq en/disable is done inside557557+1:558558+#endif559559+560560+ mov x0, sp561561+ bl exit_el1_irq_or_nmi562562+ .endm563563+564564+ .macro el0_interrupt_handler, handler:req565565+ gic_prio_irq_setup pmr=x20, tmp=x0566566+ user_exit_irqoff567567+ enable_da568568+569569+ tbz x22, #55, 1f570570+ bl do_el0_irq_bp_hardening571571+1:572572+ irq_handler \handler573573+ .endm574574+534575 .text535576536577/*···588547589548 kernel_ventry 1, sync // Synchronous EL1h590549 kernel_ventry 1, irq // IRQ EL1h591591- kernel_ventry 1, fiq_invalid // FIQ EL1h550550+ kernel_ventry 1, fiq // FIQ EL1h592551 kernel_ventry 1, error // Error EL1h593552594553 kernel_ventry 0, sync // Synchronous 64-bit EL0595554 kernel_ventry 0, irq // IRQ 64-bit EL0596596- kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0555555+ kernel_ventry 0, fiq // FIQ 64-bit EL0597556 kernel_ventry 0, error // Error 64-bit EL0598557599558#ifdef CONFIG_COMPAT600559 kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0601560 kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0602602- kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0561561+ kernel_ventry 0, fiq_compat, 32 // FIQ 32-bit EL0603562 kernel_ventry 0, error_compat, 32 // Error 32-bit EL0604563#else605564 kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0···665624 inv_entry 0, BAD_ERROR666625SYM_CODE_END(el0_error_invalid)667626668668-#ifdef CONFIG_COMPAT669669-SYM_CODE_START_LOCAL(el0_fiq_invalid_compat)670670- inv_entry 0, BAD_FIQ, 32671671-SYM_CODE_END(el0_fiq_invalid_compat)672672-#endif673673-674627SYM_CODE_START_LOCAL(el1_sync_invalid)675628 inv_entry 1, BAD_SYNC676629SYM_CODE_END(el1_sync_invalid)···695660 .align 6696661SYM_CODE_START_LOCAL_NOALIGN(el1_irq)697662 kernel_entry 1698698- gic_prio_irq_setup pmr=x20, tmp=x1699699- enable_da_f700700-701701- mov x0, sp702702- bl enter_el1_irq_or_nmi703703-704704- irq_handler705705-706706-#ifdef CONFIG_PREEMPTION707707- ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count708708-alternative_if ARM64_HAS_IRQ_PRIO_MASKING709709- /*710710- * DA_F were cleared at start of handling. If anything is set in DAIF,711711- * we come back from an NMI, so skip preemption712712- */713713- mrs x0, daif714714- orr x24, x24, x0715715-alternative_else_nop_endif716716- cbnz x24, 1f // preempt count != 0 || NMI return path717717- bl arm64_preempt_schedule_irq // irq en/disable is done inside718718-1:719719-#endif720720-721721- mov x0, sp722722- bl exit_el1_irq_or_nmi723723-663663+ el1_interrupt_handler handle_arch_irq724664 kernel_exit 1725665SYM_CODE_END(el1_irq)666666+667667+SYM_CODE_START_LOCAL_NOALIGN(el1_fiq)668668+ kernel_entry 1669669+ el1_interrupt_handler handle_arch_fiq670670+ kernel_exit 1671671+SYM_CODE_END(el1_fiq)726672727673/*728674 * EL0 mode handlers.···731715 b el0_irq_naked732716SYM_CODE_END(el0_irq_compat)733717718718+SYM_CODE_START_LOCAL_NOALIGN(el0_fiq_compat)719719+ kernel_entry 0, 32720720+ b el0_fiq_naked721721+SYM_CODE_END(el0_fiq_compat)722722+734723SYM_CODE_START_LOCAL_NOALIGN(el0_error_compat)735724 kernel_entry 0, 32736725 b el0_error_naked···746725SYM_CODE_START_LOCAL_NOALIGN(el0_irq)747726 kernel_entry 0748727el0_irq_naked:749749- gic_prio_irq_setup pmr=x20, tmp=x0750750- user_exit_irqoff751751- enable_da_f752752-753753- tbz x22, #55, 1f754754- bl do_el0_irq_bp_hardening755755-1:756756- irq_handler757757-728728+ el0_interrupt_handler handle_arch_irq758729 b ret_to_user759730SYM_CODE_END(el0_irq)731731+732732+SYM_CODE_START_LOCAL_NOALIGN(el0_fiq)733733+ kernel_entry 0734734+el0_fiq_naked:735735+ el0_interrupt_handler handle_arch_fiq736736+ b ret_to_user737737+SYM_CODE_END(el0_fiq)760738761739SYM_CODE_START_LOCAL(el1_error)762740 kernel_entry 1···777757 mov x0, sp778758 mov x1, x25779759 bl do_serror780780- enable_da_f760760+ enable_da781761 b ret_to_user782762SYM_CODE_END(el0_error)783763
+33-2
arch/arm64/kernel/irq.c
···7171}7272#endif73737474+static void default_handle_irq(struct pt_regs *regs)7575+{7676+ panic("IRQ taken without a root IRQ handler\n");7777+}7878+7979+static void default_handle_fiq(struct pt_regs *regs)8080+{8181+ panic("FIQ taken without a root FIQ handler\n");8282+}8383+8484+void (*handle_arch_irq)(struct pt_regs *) __ro_after_init = default_handle_irq;8585+void (*handle_arch_fiq)(struct pt_regs *) __ro_after_init = default_handle_fiq;8686+8787+int __init set_handle_irq(void (*handle_irq)(struct pt_regs *))8888+{8989+ if (handle_arch_irq != default_handle_irq)9090+ return -EBUSY;9191+9292+ handle_arch_irq = handle_irq;9393+ pr_info("Root IRQ handler: %ps\n", handle_irq);9494+ return 0;9595+}9696+9797+int __init set_handle_fiq(void (*handle_fiq)(struct pt_regs *))9898+{9999+ if (handle_arch_fiq != default_handle_fiq)100100+ return -EBUSY;101101+102102+ handle_arch_fiq = handle_fiq;103103+ pr_info("Root FIQ handler: %ps\n", handle_fiq);104104+ return 0;105105+}106106+74107void __init init_IRQ(void)75108{76109 init_irq_stacks();77110 init_irq_scs();78111 irqchip_init();7979- if (!handle_arch_irq)8080- panic("No interrupt controller found.");8111282113 if (system_uses_irq_prio_masking()) {83114 /*
+1-1
arch/arm64/kernel/process.c
···8484 unsigned long daif_bits;85858686 daif_bits = read_sysreg(daif);8787- write_sysreg(daif_bits | PSR_I_BIT, daif);8787+ write_sysreg(daif_bits | PSR_I_BIT | PSR_F_BIT, daif);88888989 /*9090 * Unmask PMR before going idle to make sure interrupts can