中断子系统7_中断出口处理

//	中断公共入口
1.1 common_interrupt:   //所有可屏蔽中断函数的公共入口
    SAVE_ALL    //寄存器入栈
    movl %esp,%eax  //  eax保存栈顶指针
    call do_IRQ //中断处理函数
    jmp ret_from_intr	//从中断返回

//	从中断返回
//	函数主要任务:
//		1.确定中断发生前的运行模式
//			1.1 恢复内核执行路径
//				1.1.1 检查是否内核抢占,执行内核抢占
//				1.1.2 恢复硬件上下文
//				1.1.3.iret
//			1.2 恢复用户执行路径
//				1.2.1 处理信号
//				1.2.2 恢复硬件上下文
//				1.2.3 iret
2.1 ret_from_intr:
	GET_THREAD_INFO(%ebp)	//当前进程threadinfo的指针存入寄存器EBX中
	movl EFLAGS(%esp), %eax
	movb CS(%esp), %al
	testl $(VM_MASK | 3), %eax 	//cs,eflags确定中断发生前的运行模式:1.VM86,用户空间,2.内核空间
	jz resume_kernel
ENTRY(resume_userspace)		//恢复用户空间
 	cli		//关本cpu中断,防止中断退出时被打断
	movl TI_flags(%ebp), %ecx	//threadinfo->flags
	andl $_TIF_WORK_MASK, %ecx	//处理挂起的信号
	jne work_pending
	jmp restore_all	//恢复硬件上下文

ENTRY(resume_kernel)	//恢复内核空间
	cli	//关本cpu中断,防止中断退出时被打断
	cmpl $0,TI_preempt_count(%ebp)	//内核抢占计数器
	jnz restore_all 				//内核抢占计数!=0,不可以发生内核抢占,恢复之前的内核执行路径
need_resched:						//否则,检查当前进程是否设置need_resched标志
	movl TI_flags(%ebp), %ecx
	testb $_TIF_NEED_RESCHED, %cl 	//没有设置TIF_NEED_RESCHED标志
	jz restore_all 					//恢复程序执行
	testl $IF_MASK,EFLAGS(%esp)
	jz restore_all
	call preempt_schedule_irq	//内核抢占
	jmp need_resched 			//重调度

//	恢复中断发生前程序状态
//		注:iret中断服务程序的最后一条指令。IRET指令将推入堆栈的段地址和偏移地址弹出,
//			使程序返回到原来发生中断的地方。其作用是从中断中恢复中断前的状态,具体作用有如下三点:
//			1.恢复IP(instruction pointer):(IP)←((SP)+1:(SP)),(SP)←(SP)+2
//			2.恢复CS(code segment):(CS)←((SP))+1:(SP)),(SP)←(SP)+2
//			3.恢复中断前的PSW(program status word),即恢复中断前的标志寄存器的状态。
//			(FR)←((SP)+1:(SP)),(SP)←(SP)+2
2.2 #define RESTORE_ALL	\
	RESTORE_REGS	\
	addl $4, %esp;	\
1:	iret;
//ret_from_intr 流程:

                                               

//	内核抢占入口
//	函数主要任务:
//		1.设置preempt_active,表示当前进程正在发生内核抢占
//			1.1 防止递归调用preempt_schedule_irq
//		2.开中断
//		3.调度
//		4.进程再次恢复执行,关中断,清除preempt_active,表示内核抢占完成
//		5.检查是否再次需要内核抢占
2.3 asmlinkage void __sched preempt_schedule_irq(void)
{
	struct thread_info *ti = current_thread_info();

need_resched:
	//设置preempt_active,表示正在发生内核抢占
	add_preempt_count(PREEMPT_ACTIVE);
	//在进入preempt_schedule_irq之前中断被关闭,此处开中断
	local_irq_enable();
	//调度
	schedule();
	//此进程恢复执行,关闭中断
	local_irq_disable();
	//清除preempt_active,表示内核抢占完成
	sub_preempt_count(PREEMPT_ACTIVE);
	//检查是否需要内核抢占
	barrier();
	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
		goto need_resched;
}

//	处理挂起的信号
//	函数主要任务:
//		1.检查是否需要重调度
//			1.1 调度
//			1.2 恢复执行后,检查信号是否已经被处理
//				1.2.1 如果已经被处理,恢复进程路径
//				1.2.2 重复路径1
//		2.执行信号处理函数
//		3.恢复硬件上下文
2.4 work_pending:
	testb $_TIF_NEED_RESCHED, %cl 	//检查是否需要重调度
	jz work_notifysig 				//	先执行进程调度
work_resched:
	call schedule
	cli				//关中断
	movl TI_flags(%ebp), %ecx
	andl $_TIF_WORK_MASK, %ecx	//恢复进程执行后,检查信号是否已经被处理
	jz restore_all 					//如果信号已经被处理,则直接恢复进程硬件上下文
	testb $_TIF_NEED_RESCHED, %cl 	//检查是否需进程调度
	jnz work_resched

work_notifysig:	//处理挂起的信号
	testl $VM_MASK, EFLAGS(%esp)
	movl %esp, %eax 	//检查是否在vm86模式
	jne work_notifysig_v86
	xorl %edx, %edx
	call do_notify_resume	//执行信号处理函数
	jmp restore_all
//中断嵌套

                                                         

// 参考 深入理解linux内核
//  关于x86平台下中断嵌套的讨论
//      http://blog.focus-linux.net/?p=50
时间: 2024-10-02 19:26:36

中断子系统7_中断出口处理的相关文章

中断子系统3_中断入口处理

// 中断入口 // 注:gnu 每个符号分属global(被输出)和local(不被输出)两类中的一种. 1.1 #define ENTRY(name) \ .globl name; \ ALIGN; \//之后的代码对齐到32字节,使用NOP(0x90)补齐 name: // 代码对齐 // .align(n) power-of-2对齐 // 4 对齐到16字节, 5 对齐到32字节 // 0x90 NOP 指令的机器码,用于填充到指定的对齐字节 1.2 #define ALIGN .ali

中断子系统4_i8259a中断控制器

// 8259A 中的寄存器: // ICW: Initialization Command Word,初始化命令寄存器 // OCW: Operation Command Word,操作命令字,用于控制 8259A // IRR: Interrupt Request Register,中断请求寄存器,共 8bit,对应 IR0~IR7 八个中断管脚.当某个管脚的中断请求到来后, // 若该管脚没有被屏蔽,IRR 中对应的 bit 被置1.表示 PIC 已经收到设备的中断请求,但还未提交给 CP

中断子系统1_中断子系统初始化

// 控制单元对中断信号的处理: // 当cpu执行一条指令后,cs和eip包含下一条要执行的指令的逻辑地址,在处理那条指令之前, // 控制单元会检查在运行前一条指令时是否发生了一个中断或异常,如果发生了一个中断或异常, // 控制单元执行下列操作: // 1.确定与中断或异常关联的向量i // 2.读入由idtr寄存器指向的IDT表中的第i项 // 3.从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的选择符所标识的段描述符. // 这个描述符指定中断或异常处理程序的

Linux的IRQ中断子系统分析

本文以Linux中断子系统架构为视角,旨在提供一个对Linux中断系统的全局认识,不涉及具体实现细节. 一.Linux中断子系统架构 在Linux中断子系统(generic irq)出现之前,内核使用__do_IRQ处理所有的中断,这意味着__do_IRQ中要处理各种类型的中断,这会导致软件的复杂性增加,层次不分明,而且代码的可重用性也不好.通用中断子系统的原型最初出现于ARM体系中,一开始内核的开发者们把3种中断类型区分出来(电平中断.边缘中断.简易中断),后来又针对某些需要回应eoi(end

中断子系统5_电流层处理

// 电流类型: // 1.电平型:handle_level_irq /* * Level type interrupts are active as long as the hardware line has * the active level. This may require to mask the interrupt and unmask * it after the associated handler has acknowledged the device, so the * in

linux kernel的中断子系统之(三):IRQ number和中断描述符【转】

转自:http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html 一.前言 本文主要围绕IRQ number和中断描述符(interrupt descriptor)这两个概念描述通用中断处理过程.第二章主要描述基本概念,包括什么是IRQ number,什么是中断描述符等.第三章描述中断描述符数据结构的各个成员.第四章描述了初始化中断描述符相关的接口API.第五章描述中断描述符相关的接口API. 二.基本概念 1.通用中断的代码处理

msp430 中断 结构-msp430F5529A中断程序运行卡顿

问题描述 msp430F5529A中断程序运行卡顿 菜鸟写了一段程序如下,希望实现电子秤的功能.中断的话是两个按键触发的,首次按下S1,清零:第二次按下S1进行称重:按下S2则关机. 真正运行起来卡的不行甚至动不起来,请问是不是我的主函数设计有问题? 还有求多个触发中断的例程,感觉自己写的结构确实很不合理. 谢谢啦 void main(void) { P1DIR = 0X00;//调零,按下S1+开始称重,按下S1:设置P1.7为输入状态 P1IE = 0X80;//设置P1.7开中断 P1IE

linux驱动开发--中断:按键中断

1.中断定义 中断是指cpu在执行过程中,出现了某些突发事件时cpu必须暂停执行当前的程序,转去处理突发事件,处理完毕后cpu又返回原程序被中断的位置并继续执行. 2.中断分类 3.Linux中断处理程序结构 a.在Linux系统中,中断处理程序分解为两个半部:顶半部(TopHalf)和底半部(BottomHalt). b.顶半部:完成尽可能少的比较紧急的功能,往往只是简单的读取寄存器中的中断状态并清除中断标志后就进行"登记中断"的工作,也就是将底半部处理程序挂到该设备的底半部执行队列

win7中断-关于win7中的中断号的中断问题

问题描述 关于win7中的中断号的中断问题 我看书上说x86不是有24个中断吗?为什么我用win7 32位查看的时候,中断有190了呢? 解决方案 你的教材说的是实模式,这个在386(80386是1986年问世的,比你岁数都大)以后都淘汰了,保护模式的中断机制完全不同.你学的是计算机科学还是计算机考古学?