超强的Linux中断分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
超强的Linux中断分析[日期:2008-09-13] 来源:作者:
1) IPI中断的初始化。
intr_init_hook调用apic_intr_init(),后者再调用──如果CONFIG_SMP──smp_intr_init(),
这个函数设置IPI中断的处理,然后,apic_intr_init()为另外两个IPI:SPURIOUS_APIC_VECTOR和
ERROR_APIC_VECTOR设置ISR。
2) irq_desc[NR_IRQS]
struct irq_desc,亦即irq_desc_t,描述了一个irq的属性,如irqaction、depth、
pending_mask等。
include/linux/irq.h:
struct irq_desc {
irq_flow_handler_t handle_irq;
struct irq_chip *chip;
struct msi_desc *msi_desc;
void *handler_data;
void *chip_data;
struct irqaction *action; /* IRQ action list */
unsigned int status; /* IRQ status */
unsigned int depth; /* nested irq disables */
unsigned int wake_depth; /* nested wake enables */
unsigned int irq_count; /* For detecting broken IRQs */
unsigned int irqs_unhandled;
spinlock_t lock;
#ifdef CONFIG_SMP
cpumask_t affinity;
unsigned int cpu;
#endif
#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
cpumask_t pending_mask;
#endif
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *dir;
#endif
const char *name;
} ____cacheline_internodealigned_in_smp;
Linux有一个全局变量,包含了了所有的IRQ:(kernel/irq/handle.c)
struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
[0 ... NR_IRQS-1] = {
.status = IRQ_DISABLED,
.chip = &no_irq_chip,
.handle_irq = handle_bad_irq,
.depth = 1,
.lock = SPIN_LOCK_UNLOCKED,
#ifdef CONFIG_SMP
.affinity = CPU_MASK_ALL
#endif
}
}
3) irq_chip(即在genericirq之前的hw_interrupt_type)
>以下这段是genericirq之前的:
>Linux支持N种可编程中断控制器PIC,所以有一个struct hw_interrupt_type,对于i8259A
>来说,这个结构是i8259A_irq_type,对于IOAPIC来说,根据设置为电平触发或边沿触发的方式,
>分别有ioapic_level_type和ioapic_edge_type两个不同的结构。
在引入genericirq补丁之后,定义了几个irq_chip结构:
针对i386和x86-64各有一个定义的:
ioapic_chip,
i8259A_chip,
lapic_chip,
msi_chip,
ht_irq_chip,
vmi_chip,
针对visw体系的:
cobalt_irq_chip,
piix4_master_irq_type,
piix4_virtual_irq_type
针对voyager体系的:
vic_chip
其它目的的:
no_irq_chip,
dummy_irq_chip
4) irq_stat[NR_CPUS]
Linux定义了一个全局的数组,用来描述每个CPU上的irq处理状态:(arch/i386/kernel/irq.c)
DEFINE_PER_CPU(irq_cpustat_t, irq_stat) __cacheline_internodealigned_in_smp;
EXPORT_PER_CPU_SYMBOL(irq_stat);
irq_stat_t的定义。
typedef struct {
unsigned int __softirq_pending;
unsigned long idle_timestamp;
unsigned int __nmi_count; /* arch dependent */
unsigned int apic_timer_irqs; /* arch dependent */
} ____cacheline_aligned irq_cpustat_t;
5). 中断共享
我们知道,多个中断源可以共享一个irq线。Linux的实现方式是,每个中断源都有自己的
一个struct irqaction,
irqaction结构的定义:
struct irqaction {
irq_handler_t handler;
unsigned long flags;
cpumask_t mask;
const char *name;
void *dev_id;
struct irqaction *next;
int irq;
struct proc_dir_entry *dir;
};
同一个irq可能有多个irqaction,组成一个链表。struct irq_desc中有个域: