1 // SPDX-License-Identifier: GPL-2.0 !! 1 /* 2 // Copyright (C) 2018 Hangzhou C-SKY Microsyst !! 2 * This file is subject to the terms and conditions of the GNU General Public 3 !! 3 * License. See the file "COPYING" in the main directory of this archive >> 4 * for more details. >> 5 * >> 6 * Code to handle x86 style IRQs plus some generic interrupt stuff. >> 7 * >> 8 * Copyright (C) 1992 Linus Torvalds >> 9 * Copyright (C) 1994 - 2000 Ralf Baechle >> 10 */ >> 11 #include <linux/kernel.h> >> 12 #include <linux/delay.h> 4 #include <linux/init.h> 13 #include <linux/init.h> 5 #include <linux/interrupt.h> 14 #include <linux/interrupt.h> 6 #include <linux/irq.h> !! 15 #include <linux/kernel_stat.h> 7 #include <linux/irqchip.h> !! 16 #include <linux/proc_fs.h> 8 #include <asm/traps.h> !! 17 #include <linux/mm.h> 9 #include <asm/smp.h> !! 18 #include <linux/random.h> >> 19 #include <linux/sched.h> >> 20 #include <linux/seq_file.h> >> 21 #include <linux/kallsyms.h> >> 22 #include <linux/kgdb.h> >> 23 #include <linux/ftrace.h> >> 24 >> 25 #include <linux/atomic.h> >> 26 #include <asm/uaccess.h> >> 27 >> 28 #ifdef CONFIG_KGDB >> 29 int kgdb_early_setup; >> 30 #endif >> 31 >> 32 static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; >> 33 >> 34 int allocate_irqno(void) >> 35 { >> 36 int irq; >> 37 >> 38 again: >> 39 irq = find_first_zero_bit(irq_map, NR_IRQS); >> 40 >> 41 if (irq >= NR_IRQS) >> 42 return -ENOSPC; >> 43 >> 44 if (test_and_set_bit(irq, irq_map)) >> 45 goto again; >> 46 >> 47 return irq; >> 48 } >> 49 >> 50 /* >> 51 * Allocate the 16 legacy interrupts for i8259 devices. This happens early >> 52 * in the kernel initialization so treating allocation failure as BUG() is >> 53 * ok. >> 54 */ >> 55 void __init alloc_legacy_irqno(void) >> 56 { >> 57 int i; >> 58 >> 59 for (i = 0; i <= 16; i++) >> 60 BUG_ON(test_and_set_bit(i, irq_map)); >> 61 } >> 62 >> 63 void free_irqno(unsigned int irq) >> 64 { >> 65 smp_mb__before_clear_bit(); >> 66 clear_bit(irq, irq_map); >> 67 smp_mb__after_clear_bit(); >> 68 } >> 69 >> 70 /* >> 71 * 'what should we do if we get a hw irq event on an illegal vector'. >> 72 * each architecture has to answer this themselves. >> 73 */ >> 74 void ack_bad_irq(unsigned int irq) >> 75 { >> 76 smtc_im_ack_irq(irq); >> 77 printk("unexpected IRQ # %d\n", irq); >> 78 } >> 79 >> 80 atomic_t irq_err_count; >> 81 >> 82 int arch_show_interrupts(struct seq_file *p, int prec) >> 83 { >> 84 seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); >> 85 return 0; >> 86 } >> 87 >> 88 asmlinkage void spurious_interrupt(void) >> 89 { >> 90 atomic_inc(&irq_err_count); >> 91 } 10 92 11 void __init init_IRQ(void) 93 void __init init_IRQ(void) 12 { 94 { 13 irqchip_init(); !! 95 int i; 14 #ifdef CONFIG_SMP !! 96 15 setup_smp_ipi(); !! 97 #ifdef CONFIG_KGDB >> 98 if (kgdb_early_setup) >> 99 return; >> 100 #endif >> 101 >> 102 for (i = 0; i < NR_IRQS; i++) >> 103 irq_set_noprobe(i); >> 104 >> 105 arch_init_irq(); >> 106 >> 107 #ifdef CONFIG_KGDB >> 108 if (!kgdb_early_setup) >> 109 kgdb_early_setup = 1; >> 110 #endif >> 111 } >> 112 >> 113 #ifdef CONFIG_DEBUG_STACKOVERFLOW >> 114 static inline void check_stack_overflow(void) >> 115 { >> 116 unsigned long sp; >> 117 >> 118 __asm__ __volatile__("move %0, $sp" : "=r" (sp)); >> 119 sp &= THREAD_MASK; >> 120 >> 121 /* >> 122 * Check for stack overflow: is there less than STACK_WARN free? >> 123 * STACK_WARN is defined as 1/8 of THREAD_SIZE by default. >> 124 */ >> 125 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { >> 126 printk("do_IRQ: stack overflow: %ld\n", >> 127 sp - sizeof(struct thread_info)); >> 128 dump_stack(); >> 129 } >> 130 } >> 131 #else >> 132 static inline void check_stack_overflow(void) {} 16 #endif 133 #endif >> 134 >> 135 >> 136 /* >> 137 * do_IRQ handles all normal device IRQ's (the special >> 138 * SMP cross-CPU interrupts have their own specific >> 139 * handlers). >> 140 */ >> 141 void __irq_entry do_IRQ(unsigned int irq) >> 142 { >> 143 irq_enter(); >> 144 check_stack_overflow(); >> 145 if (!smtc_handle_on_other_cpu(irq)) >> 146 generic_handle_irq(irq); >> 147 irq_exit(); >> 148 } >> 149 >> 150 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF >> 151 /* >> 152 * To avoid inefficient and in some cases pathological re-checking of >> 153 * IRQ affinity, we have this variant that skips the affinity check. >> 154 */ >> 155 >> 156 void __irq_entry do_IRQ_no_affinity(unsigned int irq) >> 157 { >> 158 irq_enter(); >> 159 smtc_im_backstop(irq); >> 160 generic_handle_irq(irq); >> 161 irq_exit(); 17 } 162 } >> 163 >> 164 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ 18 165
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.