linux 中断机制浅析

一、中断相关结构体

1.irq_desc中断描述符

struct irq_desc {
#ifdef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
	struct irq_data	irq_data;
#else
	union {
		struct irq_data	irq_data;	//中断数据
		struct {
			unsigned int	irq;	//中断号
			unsigned int	node;	//节点号
			struct irq_chip	*chip;	//irq_chip
			void	*handler_data;	
			void	*chip_data;	
			struct msi_desc	*msi_desc;
#ifdef CONFIG_SMP
			cpumask_var_t	affinity;
#endif
		};
	};
#endif
	struct timer_rand_state *timer_rand_state;
	unsigned int	*kstat_irqs;
	irq_flow_handler_t	handle_irq;	//中断处理句柄
	struct irqaction	*action;	/* 中断动作列表 */
	unsigned int	status;		/* 中断状态 */
	unsigned int	depth;		/* nested irq disables */
	unsigned int	wake_depth;	/* nested wake enables */
	unsigned int	irq_count;	/* For detecting broken IRQs */
	unsigned long	last_unhandled;	/* Aging timer for unhandled count */
	unsigned int	irqs_unhandled;
	raw_spinlock_t	lock;
#ifdef CONFIG_SMP
	const struct cpumask	*affinity_hint;
#ifdef CONFIG_GENERIC_PENDING_IRQ
	cpumask_var_t	pending_mask;
#endif
#endif
	atomic_t	threads_active;
	wait_queue_head_t	wait_for_threads;
#ifdef CONFIG_PROC_FS
	struct proc_dir_entry	*dir;	//proc接口目录
#endif
	const char	*name;	//名字
} ____cacheline_internodealigned_in_smp;


2.irq_chip 芯片相关的处理函数集合

struct irq_chip {	//芯片相关的处理函数集合
	const char	*name;	//"proc/interrupts/name"
#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
	unsigned int	(*startup)(unsigned int irq);	
	void	(*shutdown)(unsigned int irq);	
	void	(*enable)(unsigned int irq);	
	void	(*disable)(unsigned int irq);	
	void	(*ack)(unsigned int irq);
	void	(*mask)(unsigned int irq);
	void	(*mask_ack)(unsigned int irq);
	void	(*unmask)(unsigned int irq);
	void	(*eoi)(unsigned int irq);
	void	(*end)(unsigned int irq);
	int		(*set_affinity)(unsigned int irq,const struct cpumask *dest);
	int		(*retrigger)(unsigned int irq);
	int		(*set_type)(unsigned int irq, unsigned int flow_type);
	int		(*set_wake)(unsigned int irq, unsigned int on);
	void	(*bus_lock)(unsigned int irq);
	void	(*bus_sync_unlock)(unsigned int irq);
#endif
	unsigned int	(*irq_startup)(struct irq_data *data);	//中断开始
	void	(*irq_shutdown)(struct irq_data *data);	//中断关闭
	void	(*irq_enable)(struct irq_data *data);	//中断使能
	void	(*irq_disable)(struct irq_data *data);	//中断禁用
	void	(*irq_ack)(struct irq_data *data);
	void	(*irq_mask)(struct irq_data *data);
	void	(*irq_mask_ack)(struct irq_data *data);
	void	(*irq_unmask)(struct irq_data *data);
	void	(*irq_eoi)(struct irq_data *data);
	int		(*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
	int		(*irq_retrigger)(struct irq_data *data);
	int		(*irq_set_type)(struct irq_data *data, unsigned int flow_type);
	int		(*irq_set_wake)(struct irq_data *data, unsigned int on);
	void	(*irq_bus_lock)(struct irq_data *data);
	void	(*irq_bus_sync_unlock)(struct irq_data *data);
#ifdef CONFIG_IRQ_RELEASE_METHOD
	void	(*release)(unsigned int irq, void *dev_id);
#endif
};


3.irqaction中断行动结构体

struct irqaction {
	irq_handler_t handler;	//中断处理函数
	unsigned long flags;	//中断标志
	const char *name;		//中断名
	void *dev_id;		//设备id号,共享中断用
	struct irqaction *next;	//共享中断类型指向下一个irqaction
	int irq;			//中断号
	struct proc_dir_entry *dir;	//proc接口目录
	irq_handler_t thread_fn;	//中断处理函数(线程)
	struct task_struct *thread;	//线程任务
	unsigned long thread_flags;	//线程标志
};

 在整个中断系统中将勾勒出以下的关系框图

二、中断初始化工作

 从start_kernel看起,大致按以下的分支顺序初始化

start_kernel
	setup_arch			//设置全局init_arch_irq函数
		early_trap_init	//搬移向量表
	early_irq_init();	//初始化全局irq_desc数组
	init_IRQ();			//调用init_arch_irq函数
		[	//板级中断初始化常用到的API
		set_irq_chip
		set_irq_handler
		set_irq_chained_handler
		set_irq_flags
		set_irq_type
		set_irq_chip_data
		set_irq_data
		]

1.在setup_arch中主要是设置全局init_arch_irq函数

void __init setup_arch(char **cmdline_p)
{
	struct tag *tags = (struct tag *)&init_tags;
	struct machine_desc *mdesc;
	char *from = default_command_line;

	init_tags.mem.start = PHYS_OFFSET;
	unwind_init();
	setup_processor();
	mdesc = setup_machine(machine_arch_type);
	machine_name = mdesc->name;
	if (mdesc->soft_reboot)
		reboot_setup("s");
	if (__atags_pointer)
		tags = phys_to_virt(__atags_pointer);
	else if (mdesc->boot_params) {
#ifdef CONFIG_MMU
		if (mdesc->boot_params < PHYS_OFFSET ||mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
			printk(KERN_WARNING"Default boot params at physical 0x%08lx out of reach\n",mdesc->boot_params);
		} 
		else
#endif
		{
			tags = phys_to_virt(mdesc->boot_params);
		}
	}
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
	if (tags->hdr.tag != ATAG_CORE)
		convert_to_tag_list(tags);
#endif
	if (tags->hdr.tag != ATAG_CORE)
		tags = (struct tag *)&init_tags;
	if (mdesc->fixup)
		mdesc->fixup(mdesc, tags, &from, &meminfo);
	if (tags->hdr.tag == ATAG_CORE) {
		if (meminfo.nr_banks != 0)
			squash_mem_tags(tags);
		save_atags(tags);
		parse_tags(tags);
	}
	init_mm.start_code = (unsigned long) _text;
	init_mm.end_code   = (unsigned long) _etext;
	init_mm.end_data   = (unsigned long) _edata;
	init_mm.brk	   = (unsigned long) _end;
	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
	*cmdline_p = cmd_line;
	parse_early_param();
	arm_memblock_init(&meminfo, mdesc);
	paging_init(mdesc);
	request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
	if (is_smp())
		smp_init_cpus();
#endif
	reserve_crashkernel();
	cpu_init();
	tcm_init();
	arch_nr_irqs = mdesc->nr_irqs;
	init_arch_irq = mdesc->init_irq;	//设置全局init_arch_irq函数
	//void (*init_arch_irq)(void) __initdata = NULL;
	system_timer = mdesc->timer;
	init_machine = mdesc->init_machine;
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
	conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
	conswitchp = &dummy_con;
#endif
#endif
	early_trap_init();//调用early_trap_init函数
}

1.1.early_trap_init主要挪移了中断向量表到特定位置

void __init early_trap_init(void)
{
	unsigned long vectors = CONFIG_VECTORS_BASE;	//0xffff0000
	extern char __stubs_start[], __stubs_end[];
	extern char __vectors_start[], __vectors_end[];
	extern char __kuser_helper_start[], __kuser_helper_end[];
	int kuser_sz = __kuser_helper_end - __kuser_helper_start;

	memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);	//移动中断向量表
	memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);	//移动__stubs_start段
	memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
	kuser_get_tls_init(vectors);
	memcpy((void *)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值