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 #include <linux/irqdomain.h> >> 25 >> 26 #include <linux/atomic.h> >> 27 #include <linux/uaccess.h> >> 28 >> 29 void *irq_stack[NR_CPUS]; >> 30 >> 31 /* >> 32 * 'what should we do if we get a hw irq event on an illegal vector'. >> 33 * each architecture has to answer this themselves. >> 34 */ >> 35 void ack_bad_irq(unsigned int irq) >> 36 { >> 37 printk("unexpected IRQ # %d\n", irq); >> 38 } >> 39 >> 40 atomic_t irq_err_count; >> 41 >> 42 int arch_show_interrupts(struct seq_file *p, int prec) >> 43 { >> 44 seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); >> 45 return 0; >> 46 } >> 47 >> 48 asmlinkage void spurious_interrupt(void) >> 49 { >> 50 atomic_inc(&irq_err_count); >> 51 } 10 52 11 void __init init_IRQ(void) 53 void __init init_IRQ(void) 12 { 54 { 13 irqchip_init(); !! 55 int i; 14 #ifdef CONFIG_SMP !! 56 unsigned int order = get_order(IRQ_STACK_SIZE); 15 setup_smp_ipi(); !! 57 >> 58 for (i = 0; i < NR_IRQS; i++) >> 59 irq_set_noprobe(i); >> 60 >> 61 if (cpu_has_veic) >> 62 clear_c0_status(ST0_IM); >> 63 >> 64 arch_init_irq(); >> 65 >> 66 for_each_possible_cpu(i) { >> 67 void *s = (void *)__get_free_pages(GFP_KERNEL, order); >> 68 >> 69 irq_stack[i] = s; >> 70 pr_debug("CPU%d IRQ stack at 0x%p - 0x%p\n", i, >> 71 irq_stack[i], irq_stack[i] + IRQ_STACK_SIZE); >> 72 } >> 73 } >> 74 >> 75 #ifdef CONFIG_DEBUG_STACKOVERFLOW >> 76 static inline void check_stack_overflow(void) >> 77 { >> 78 unsigned long sp; >> 79 >> 80 __asm__ __volatile__("move %0, $sp" : "=r" (sp)); >> 81 sp &= THREAD_MASK; >> 82 >> 83 /* >> 84 * Check for stack overflow: is there less than STACK_WARN free? >> 85 * STACK_WARN is defined as 1/8 of THREAD_SIZE by default. >> 86 */ >> 87 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { >> 88 printk("do_IRQ: stack overflow: %ld\n", >> 89 sp - sizeof(struct thread_info)); >> 90 dump_stack(); >> 91 } >> 92 } >> 93 #else >> 94 static inline void check_stack_overflow(void) {} 16 #endif 95 #endif >> 96 >> 97 >> 98 /* >> 99 * do_IRQ handles all normal device IRQ's (the special >> 100 * SMP cross-CPU interrupts have their own specific >> 101 * handlers). >> 102 */ >> 103 void __irq_entry do_IRQ(unsigned int irq) >> 104 { >> 105 irq_enter(); >> 106 check_stack_overflow(); >> 107 generic_handle_irq(irq); >> 108 irq_exit(); >> 109 } >> 110 >> 111 #ifdef CONFIG_IRQ_DOMAIN >> 112 void __irq_entry do_domain_IRQ(struct irq_domain *domain, unsigned int hwirq) >> 113 { >> 114 struct irq_desc *desc; >> 115 >> 116 irq_enter(); >> 117 check_stack_overflow(); >> 118 >> 119 desc = irq_resolve_mapping(domain, hwirq); >> 120 if (likely(desc)) >> 121 handle_irq_desc(desc); >> 122 >> 123 irq_exit(); 17 } 124 } >> 125 #endif 18 126
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.