博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
慢慢欣赏linux 继续深入学习x86中断
阅读量:4071 次
发布时间:2019-05-25

本文共 6726 字,大约阅读时间需要 22 分钟。

中断控制器描述符定义

struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {	[0 ... NR_IRQS-1] = {		.handle_irq	= handle_bad_irq,		.depth		= 1,		.lock		= __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),	}};

初始化流程

int __init early_irq_init(void){	desc = irq_desc;	count = ARRAY_SIZE(irq_desc);	for (i = 0; i < count; i++) {		desc[i].kstat_irqs = alloc_percpu(unsigned int);		alloc_masks(&desc[i], node);		raw_spin_lock_init(&desc[i].lock);		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);		desc_set_defaults(i, &desc[i], node, NULL, NULL);	}	return arch_early_irq_init();	=>int __init arch_early_irq_init(void)	{		struct fwnode_handle *fn = irq_domain_alloc_named_fwnode("VECTOR");				x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops,							   NULL);		=>static const struct irq_domain_ops x86_vector_domain_ops = {			.alloc		= x86_vector_alloc_irqs,			.free		= x86_vector_free_irqs,			.activate	= x86_vector_activate,			.deactivate	= x86_vector_deactivate,		#ifdef CONFIG_GENERIC_IRQ_DEBUGFS			.debug_show	= x86_vector_debug_show,		#endif		};			=>static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,				 unsigned int nr_irqs, void *arg)			{				struct irq_alloc_info *info = arg;				struct apic_chip_data *apicd;				struct irq_data *irqd;				int i, err, node;				for (i = 0; i < nr_irqs; i++) {					irqd = irq_domain_get_irq_data(domain, virq + i);					node = irq_data_get_node(irqd);					WARN_ON_ONCE(irqd->chip_data);					apicd = alloc_apic_chip_data(node);					apicd->irq = virq + i;					irqd->chip = &lapic_controller;					irqd->chip_data = apicd;					irqd->hwirq = virq + i;					irqd_set_single_target(irqd);					/*					 * Legacy vectors are already assigned when the IOAPIC					 * takes them over. They stay on the same vector. This is					 * required for check_timer() to work correctly as it might					 * switch back to legacy mode. Only update the hardware					 * config.					 */					if (info->flags & X86_IRQ_ALLOC_LEGACY) {						if (!vector_configure_legacy(virq + i, irqd, apicd))							continue;					}					err = assign_irq_vector_policy(irqd, info);					=>static int					assign_irq_vector_policy(struct irq_data *irqd, struct irq_alloc_info *info)					{						if (irqd_affinity_is_managed(irqd))							return reserve_managed_vector(irqd);						if (info->mask)							return assign_irq_vector(irqd, info->mask);							=>static int assign_irq_vector(struct irq_data *irqd, const struct cpumask *dest)							{								unsigned long flags;								int ret;								raw_spin_lock_irqsave(&vector_lock, flags);								cpumask_and(vector_searchmask, dest, cpu_online_mask);								ret = assign_vector_locked(irqd, vector_searchmask);								=>static int assign_vector_locked(struct irq_data *irqd,												const struct cpumask *dest)								{									struct apic_chip_data *apicd = apic_chip_data(irqd);									int vector = allocate_vector(irqd, dest);									=>static int allocate_vector(struct irq_data *irqd, const struct cpumask *dest)									{										struct apic_chip_data *apicd = apic_chip_data(irqd);										bool resvd = apicd->has_reserved;										unsigned int cpu = apicd->cpu;										int vector = apicd->vector;										lockdep_assert_held(&vector_lock);										/*										 * If the current target CPU is online and in the new requested										 * affinity mask, there is no point in moving the interrupt from										 * one CPU to another.										 */										if (vector && cpu_online(cpu) && cpumask_test_cpu(cpu, dest))											return 0;										vector = irq_matrix_alloc(vector_matrix, dest, resvd, &cpu);										if (vector > 0)											apic_update_vector(irqd, vector, cpu);											=>static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,															   unsigned int newcpu)											{												struct apic_chip_data *apicd = apic_chip_data(irqd);												struct irq_desc *desc = irq_data_to_desc(irqd);												bool managed = irqd_affinity_is_managed(irqd);												/*												 * If there is no vector associated or if the associated vector is												 * the shutdown vector, which is associated to make PCI/MSI												 * shutdown mode work, then there is nothing to release. Clear out												 * prev_vector for this and the offlined target case.												 */												apicd->prev_vector = 0;												if (!apicd->vector || apicd->vector == MANAGED_IRQ_SHUTDOWN_VECTOR)													goto setnew;												/*												 * If the target CPU of the previous vector is online, then mark												 * the vector as move in progress and store it for cleanup when the												 * first interrupt on the new vector arrives. If the target CPU is												 * offline then the regular release mechanism via the cleanup												 * vector is not possible and the vector can be immediately freed												 * in the underlying matrix allocator.												 */												if (cpu_online(apicd->cpu)) {													apicd->move_in_progress = true;													apicd->prev_vector = apicd->vector;													apicd->prev_cpu = apicd->cpu;												} else {													irq_matrix_free(vector_matrix, apicd->cpu, apicd->vector,															managed);												}											setnew:												apicd->vector = newvec;												apicd->cpu = newcpu;												BUG_ON(!IS_ERR_OR_NULL(per_cpu(vector_irq, newcpu)[newvec]));												per_cpu(vector_irq, newcpu)[newvec] = desc;	// vector_irq与中断控制器描述符联系起来											}										return vector;									}									apic_update_irq_cfg(irqd, apicd->vector, apicd->cpu);									return 0;								}								raw_spin_unlock_irqrestore(&vector_lock, flags);								return ret;							}						/*						 * Make only a global reservation with no guarantee. A real vector						 * is associated at activation time.						 */						return reserve_irq_vector(irqd);					}				}				return 0;			}							   				irq_domain_free_fwnode(fn);		irq_set_default_host(x86_vector_domain);		arch_init_msi_domain(x86_vector_domain);		/*		 * Allocate the vector matrix allocator data structure and limit the		 * search area.		 */		vector_matrix = irq_alloc_matrix(NR_VECTORS, FIRST_EXTERNAL_VECTOR,						 FIRST_SYSTEM_VECTOR);		return arch_early_ioapic_init();	}}

linux驱动中断不能睡眠的原因

http://blog.chinaunix.net/uid-24866549-id-4611653.html

内核IRQ中断向量

https://blog.csdn.net/sinat_20184565/article/details/98095894

x86架构下Linux中断IDT建立及中断处理过程之1    博客不错

https://blog.csdn.net/baidu_31504167/article/details/100556391

x86架构下Linux中断处理之request_irq

https://blog.csdn.net/baidu_31504167/article/details/101712674

early_irq_init

https://blog.csdn.net/wuye110/article/details/78556622

x86架构下Linux中断处理之early_irq_init

https://blog.csdn.net/baidu_31504167/article/details/101673798

ARM-Linux中断系统

你可能感兴趣的文章
java自定义容器排序的两种方法
查看>>
如何成为编程高手
查看>>
本科生的编程水平到底有多高
查看>>
使用与或运算完成两个整数的相加
查看>>
备忘:java中的递归
查看>>
Solr及Spring-Data-Solr入门学习
查看>>
python_time模块
查看>>
python_configparser(解析ini)
查看>>
selenium学习资料
查看>>
<转>文档视图指针互获
查看>>
从mysql中 导出/导入表及数据
查看>>
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
swiper插件的的使用
查看>>
layui插件的使用
查看>>
JS牛客网编译环境的使用
查看>>
9、VUE面经
查看>>
关于进制转换的具体实现代码
查看>>
Golang 数据可视化利器 go-echarts ,实际使用
查看>>