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

//	控制单元对中断信号的处理:
//		当cpu执行一条指令后,cs和eip包含下一条要执行的指令的逻辑地址,在处理那条指令之前,
//		控制单元会检查在运行前一条指令时是否发生了一个中断或异常,如果发生了一个中断或异常,
//		控制单元执行下列操作:
//			1.确定与中断或异常关联的向量i
//			2.读入由idtr寄存器指向的IDT表中的第i项
//			3.从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的选择符所标识的段描述符。
//				这个描述符指定中断或异常处理程序的基地址
//			4.权限和安全性检查
//			5.检查是否发生了特权级的变化,也就是说,CPL是否不同于所选择的段描述符的DPL,如果是,
//			控制单元必须开始使用与新的特权级相关的栈。
//				5.1 读入tr寄存器,以访问运行进程的TSS段
//				5.2 用与新特权级相关的栈段和栈指针的正确值装在ss和esp,这些值可以在tss中找到。
//				5.3 在新的栈中保存ss和esp以前的值,这些值定义了与旧特权级相关的栈的逻辑地址。
//			6.如果故障已发生,用引起异常的指令地址装载cs和eip寄存器,从而使得这条指令能再次被执行。
//			7.在栈中保存eflags,cs,及eip的内容。
//			8.如果异常产生了一个硬件出错码,则将其保存在栈中。
//			9.装载cs和eip寄存器,其值分别时IDT表中第i项门描述符的段选择符和偏移量字段。这些值给出了
//			中断或者异常处理程序的第一条指令地址。
//			10.由中断处理程序,执行中断处理。
//			11.中断或异常处理完毕后,相应的处理程序必须产生一条iret指令,把控制权转交给被中断的程序,
//			迫使控制单元:
//				11.1 用保存在栈中的值装载cs、eip或eflags寄存器。
//				11.2 检查处理程序的CPL是否等于cs中最低两位的值(这意味着被中断的进程与处理程序运行在
//				同一特权级),如果是,iret终止执行;否则,转入下一步
//				11.3 从栈中装载ss和esp寄存器,因此返回到与旧特权级相关的栈。

//	中断向量:
//		1.每个中断和异常是由0~255之间的一个数来标识的,intel将这个8位的无符号整数叫做一个向量。
//		2.中断向量是Intel从IA-32 CPU角度看到的中断信号划分;中断号则是Linux系统对外部中断的号码分配。
//			当外设把中断信号递送给PIC时,与之关联的是一个“中断号”(每个中断号对应一条中断线,从软件的角度来看,这两个术语可以混用);
//			当PIC把这个中断信号发送给CPU时,与之关联的是一个“中断向量”。
//		3.通常,不可屏蔽中断和异常的中断向量是固定的,而可屏蔽中断的中断向量则可以对中断控制器进行编程来改变。
//		4.i386 CPU的256个中断向量是这样分配的:
//			4.1 0~31这一共32个向量用于异常和不可屏蔽中断。
//			4.2 32~47这一共16个向量用于可屏蔽中断,分别对应于主、从8259A中断控制器的IRQ输入线
//			4.3 剩余的48~255用于标识软中断
//		5.Linux全部使用了0~47之间的向量。但对于48-255之间的软中断向量,Linux只使用了其中的一个,即用于实现系统调用的中断向量128(0x80)。
//			当用户态下的进程执行一条int 0x80汇编指令时,CPU切换到内核态,以服务于系统调用。

//	i386的IDT
//		i386 CPU的IDT表一共有256项,分别对应每一个中断向量。每一个表项就是一个中断描述符,用以描述相对应的中断向量,中断向量就是该描述符
//		在IDT中的索引,每一个中断描述符的大小都是8个字节。根据INTEL的术语,中断描述符也称为“门(Gate)”。  

//	IDT表
//		idt_table首地址保存在idt寄存器中
1.1 struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };

//	CPU异常初始化
//	调用路径:	start_kernel->trap_init
//	函数主要任务:
//		1.初始化apic控制器
//		2.注册0~19号异常、中断的处理函数,128号系统调用处理程序
//		3.注册系统调用的处理函数
//		4.cpu的初始化

//	内核源码:arch/x86/kernel/traps.c
//			  arch/x86/kernel/entry_32.S
1.2 void __init trap_init(void)
{
	//cpu内部apic控制器
	init_apic_mappings();
	//初始化中断、异常、陷阱门描述符
	set_trap_gate(0,÷_error);
	set_intr_gate(1,&debug);
	//不可屏蔽中断
	set_intr_gate(2,&nmi);
	//系统中断门
	set_system_intr_gate(3, &int3);
	//系统门
	set_system_gate(4,&overflow);
	set_system_gate(5,&bounds);
	//陷阱门
	set_trap_gate(6,&invalid_op);
	set_trap_gate(7,&device_not_available);
	set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
	set_trap_gate(9,&coprocessor_segment_overrun);
	set_trap_gate(10,&invalid_TSS);
	set_trap_gate(11,&segment_not_present);
	set_trap_gate(12,&stack_segment);
	set_trap_gate(13,&general_protection);
	//缺页中断
	set_intr_gate(14,&page_fault);
	set_trap_gate(15,&spurious_interrupt_bug);
	set_trap_gate(16,&coprocessor_error);
	set_trap_gate(17,&alignment_check);
	set_trap_gate(19,&simd_coprocessor_error);
	//系统调用描述符
	set_system_gate(SYSCALL_VECTOR,&system_call);
	//cpu相关的初始化
	cpu_init();
}

//	set_XXX_gate的设置异常处理函数地址
//		intr_gate、trap_gate区别在于DPL不同

//	设置中断门描述符
//	函数主要任务:
//		在IDT表的第n个表项插入一个中断门
//			1.1 门中的段选择子设置为内核代码段的段选择子
//			1.2 偏移量设置为中断处理程序的地址addr
//			1.3 DPL字段设置为0
1.3 void set_intr_gate(unsigned int n, void *addr)
{
	_set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
}

//	第一个外设中断(即8259A的IRQ0)所对应的中断向量
#define FIRST_EXTERNAL_VECTOR 0x20
//	系统调用的中断向量
#define SYSCALL_VECTOR 0x80

//	中断初始化
//	调用路径:start_kernel->init_IRQ
//	函数主要任务:
//		1.初始化中断描述符的中断控制器
//		2.初始化20~255号中断的入口处理函数
//		3.添加体系结构特定的门
//		4.初始化时钟中断
//		5.初始化当前cpu的中断栈
2.1 void __init init_IRQ(void)
{
	int i;

	//建立中断描述符与中断控制器的联系
	pre_intr_init_hook();

	//设置20~255号中断的入口函数
	for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
		//从第一个外部中断开始
		int vector = FIRST_EXTERNAL_VECTOR + i;
		if (i >= NR_IRQS)
			break;
		//中断门描述符
		if (vector != SYSCALL_VECTOR)
			set_intr_gate(vector, interrupt[i]);
	}
	//添加体系结构特定的门
	intr_init_hook();
	//初始化时钟中断
	setup_pit_timer();
	//初始化当前cpu的中断栈
	irq_ctx_init(smp_processor_id());
}
//	中断描述符(IRQn描述符)
//		i8259a使用0~15号IRQ
2.2 struct irqdesc irq_desc[NR_IRQS];

//	中断描述符初始化
//	函数主要任务:
//		1.禁用所有IRQ
//		2.0~15号IRQ关联i8259a中断控制器
//	注:
//		中断关闭嵌套,当depth=0时,中断开启。
2.3 void __init init_ISA_irqs (void)
{
	int i;
	//初始化cpu的apic
	init_bsp_APIC();
	//初始化8259a中断控制器
	init_8259A(0);
	//8259使用的中断号(IRQn)
	for (i = 0; i < NR_IRQS; i++) {
		//初始化时,所有irq关闭
		irq_desc[i].status = IRQ_DISABLED;
		//没有驱动注册中断处理例程
		irq_desc[i].action = NULL;
		//嵌套深度为1的关闭状态
		irq_desc[i].depth = 1;
		//0~16号irq,关联i8259a中断控制器
		if (i < 16) {
			irq_desc[i].handler = &i8259A_irq_type;
		} else {
			// >16的pci中断,按需分配
			irq_desc[i].handler = &no_irq_type;
		}
	}
}
时间: 2024-09-20 09:31:37

中断子系统1_中断子系统初始化的相关文章

调度子系统1_调度子系统初始化

unsigned int sysctl_sched_rt_period = 1000000; int sysctl_sched_rt_runtime = 950000; // 参考: // SMP负载均衡 // http://soft.chinabyte.com/os/22/12359522.shtml // linux组调度浅析 // http://hi.baidu.com/_kouu/item/0fe32610e493314be75e06d1 // 进程调度和组调度 // http://bl

Linux中断(interrupt)子系统之一:中断系统基本原理【转】

转自:http://blog.csdn.net/DroidPhone/article/details/7445825 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 设备中断控制器和CPU IRQ编号 在驱动程序中申请中断 通用中断子系统Generic irq的软件抽象 irq描述结构struct irq_desc 中断子系统的proc文件接口 这个中断系列文章主要针对移动设备中的Linux进行讨论,文中的例子基本都是基于ARM这一体系架构,其他架构的原理其实也差不多,区

Linux中断(interrupt)子系统之三:中断流控处理层【转】

转自:http://blog.csdn.net/droidphone/article/details/7489756 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 中断流控层简介 handle_simple_irq handle_level_irq handle_edge_irq handle_fasteoi_irq handle_percpu_irq handle_nested_irq 1.  中断流控层简介 早期的内核版本中,几乎所有的中断都是由__do_IRQ函数

Linux中断(interrupt)子系统之四:驱动程序接口层 &amp; 中断通用逻辑层【转】

转自:http://blog.csdn.net/droidphone/article/details/7497787 在本系列文章的第一篇:Linux中断(interrupt)子系统之一:中断系统基本原理,我把通用中断子系统分为了4个层次,其中的驱动程序接口层和中断通用逻辑层的界限实际上不是很明确,因为中断通用逻辑层的很多接口,既可以被驱动程序使用,也可以被硬件封装层使用,所以我把这两部分的内容放在一起进行讨论. 本章我将会讨论这两层对外提供的标准接口和内部实现机制,几乎所有的接口都是围绕着ir

中断子系统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

中断子系统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

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

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

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

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

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

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