Linux x86_64内核中断初始化
中断分类
Linux系统中,中断分为:
硬中断:由外部设备或者执行异常产生的需要快速处理的中断。如缺页中断、定时器硬件中断。
根据内部产生还是外部产生,分为:
- 异常:异常是内部产生的中断,不可屏蔽。
- 外部中断:外部中断是由外部设备产生的,可以屏蔽。
软中断:
软中断是Linux系统中断处理的底半处理部分,是Linux模拟的中断。为了加快硬件中断的处理,防止数据的丢失,Linux对中断处理分为顶半处理和底半处理两部分,顶半处理程序快速处理硬件事件,把不是那么紧急的逻辑放到底半处理程序中,可以简单的认为硬终端处理程序为顶半处理程序,软中断处理程序为底半处理程序。软中断一般在硬中断处理程序执行后才会执行。但是当硬中断嵌套的时候,软中断会在所有的硬中断处理完毕后才会处理,当软中断太多,会放到ksoftirqd线程中处理。
内核初始化-中断
intel处理器有256个硬中断号。其中前32个中断号为异常使用,在内核初始化的时候进行初始化。内核初始化的代码流程如下:
可以看到首先初始化异常处理,再初始化部分外部中断,再初始化一部分软中断处理。
asmlinkage void __init start_kernel(void)
{
lock_kernel();
...
//初始化调度模块
sched_init();
...
sort_main_extable();
// 初始化异常处理。
trap_init();
...
// 初始化外部中断
init_IRQ();
...
// 初始化定时器模块,同时,会注册定时器的软中断处理函数。
init_timers();
// 初始化软中断)
softirq_init();
time_init();
...
// 初始化
acpi_early_init();
}
异常中断初始化
异常中断在内核中称为trap,异常中断初始化代码为
//门初始化。初始化中断向量表。系统有固定的256个硬件中断向量。
void __init trap_init(void)
{
set_intr_gate(0,÷_error);
set_intr_gate_ist(1,&debug,DEBUG_STACK);
set_intr_gate_ist(2,&nmi,NMI_STACK);
set_intr_gate(3,&int3);
set_system_gate(4,&overflow); /* int4-5 can be called from all */
set_system_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
set_intr_gate(7,&device_not_available);
set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK);
set_intr_gate(9,&coprocessor_segment_overrun);
set_intr_gate(10,&invalid_TSS);
set_intr_gate(11,&segment_not_present);
set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK);
set_intr_gate(13,&general_protection);
set_intr_gate(14,&page_fault);
set_intr_gate(15,&spurious_interrupt_bug);
set_intr_gate(16,&coprocessor_error);
set_intr_gate(17,&alignment_check);
#ifdef CONFIG_X86_MCE
set_intr_gate_ist(18,&machine_check, MCE_STACK);
#endif
set_intr_gate(19,&simd_coprocessor_error);
#ifdef CONFIG_IA32_EMULATION
set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
#endif
set_intr_gate(KDB_VECTOR, call_debug);
/*
* Should be a barrier for any external CPU state.
*/
cpu_init();
}
总结如下:
中断向量号 | 异常事件 | Linux的处理程序 |
---|---|---|
0 | 除法错误 | Divide_error |
1 | 调试异常 | Debug |
2 | NMI中断 | Nmi |
3 | 单字节,int 3 | Int3 |
4 | 溢出 | Overflow |
5 | 边界监测中断 | Bounds |
6 | 无效操作码 | Invalid_op |
7 | 设备不可用 | Device_not_available |
8 | 双重故障 | Double_fault |
9 | 协处理器段溢出 | Coprocessor_segment_overrun |
10 | 无效TSS | Incalid_tss |
11 | 缺段中断 | Segment_not_present |
12 | 堆栈异常 | Stack_segment |
13 | 一般保护异常 | General_protection |
14 | 页异常 | Page_fault |
15 | Spurious_interrupt_bug | |
16 | 协处理器出错 | Coprocessor_error |
17 | 对齐检查中断 | Alignment_check |
0x80 | 系统调用 | ia32_syscall |
0xf9 | 内核调试 | call_debug |
上述中断处理函数都是汇编语言编写。一部分汇编直接处理完毕,一部分通过调用C函数帮助处理。
汇编代码在linux/arch/x86_64/entry.S
中,大部分都是调用C函数do_中断处理函数名
处理。
整理如下:
中断向量号 | 异常事件 | Linux汇编 | 调用c函数 | 处理结果 |
---|---|---|---|---|
0 | 除法错误 | Divide_error | do_divide_error | 发送SIGFPE信号 |
1 | 调试异常 | Debug | do_debug | 发送SIGTRAP信号 |
2 | NMI中断 | Nmi | do_nmi | |
3 | 单字节,int 3 | Int3 | do_int3 | 发送SIGTRAP信号 |
4 | 溢出 | Overflow | do_overflow | 发送SIGSEGV信号 |
5 | 边界监测中断 | Bounds | do_bounds | 发送SIGSEGV信号 |
6 | 无效操作码 | Invalid_op | do_invalid_op | 发送SIGILL信号 |
7 | 设备不可用 | Device_not_available | math_state_restore | 发送SIGSEGV信号 |
8 | 双重故障 | Double_fault | do_double_fault | |
9 | 协处理器段溢出 | Coprocessor_segment_overrun | do_coprocessor_segment_overrun | 发送SIGFPE信号 |
10 | 无效TSS | Invalid_tss | do_invalid_TSS | 发送SIGSEGV信号 |
11 | 缺段中断 | Segment_not_present | do_segment_not_present | 发送SIGBUS信号 |
12 | 堆栈异常 | Stack_segment | do_stack_segment | |
13 | 一般保护异常 | General_protection | do_general_protection | |
14 | 页异常 | Page_fault | do_page_fault | 处理缺页中断 |
15 | Spurious_interrupt_bug | do_spurious_interrupt_bug | ||
16 | 协处理器出错 | Coprocessor_error | do_coprocessor_error | 发送SIGFPE信号 |
17 | 对齐检查中断 | Alignment_check | do_alignment_check | 发送SIGBUS信号 |
0x80 | 系统调用 | ia32_syscall | ||
0xf9 | 内核调试 | call_debug | do_call_debug |
外部中断初始化
中断控制器硬件APIC分为两种:本地APIC和全局APIC。本地APIC集成在CPU内部,每个CPU都有一个,用于处理本地中断请求,CPU可以通过APIC向其他CPU发送中断,现在主要用于CPU之间的通信(IPI)。全局APIC主要是连接外部设备,用于外部设备的中断。在内核中断初始化的时候,会初始化三个与IPI相关中断。
void __init init_IRQ(void)
{
int i;
/**
* 该函数主要是初始化硬件
* 1. 初始化本地APIC控制芯片
* 2. 初始化8259A芯片
/
init_ISA_irqs();
/*
* 清空32以后的中断向量表。(除了系统调用和内核调试用的中断号)
*/
for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
int vector = FIRST_EXTERNAL_VECTOR + i;
if (i >= NR_IRQS)
break;
if (vector != IA32_SYSCALL_VECTOR && vector != KDB_VECTOR) {
set_intr_gate(vector, interrupt[i]);
}
}
// 多处理器通信中断
#ifdef CONFIG_SMP
set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
#endif
// 本地APIC中断
#ifdef CONFIG_X86_LOCAL_APIC
/* self generated IPI for local APIC timer */
set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
#endif
setup_timer();
if (!acpi_ioapic)
setup_irq(2, &irq2);
}
总结如下:
中断向量号 | 中断名 | 异常事件 | 中断处理函数 | 调用c函数 | 处理结果 |
---|---|---|---|---|---|
0xfc | RESCHEDULE_VECTOR | 处理器间中断, 用于cpu之间同学,其他cpu要求重新调度 | reschedule_interrupt | smp_reschedule_interrupt | 将线程调度标志置为需要重新调度。之后内核检查标志的时候会重新调度线程 |
0xfd | INVALIDATE_TLB_VECTOR | 处理器间中断, 用于cpu之间通信,其他cpu要求TLB缓存失效 | invalidate_interrupt | smp_invalidate_interrupt | cpu刷新TLB |
0xfa | CALL_FUNCTION_VECTOR | 处理器间中断, 用于cpu之间通信,让另外的cpu调用某个函数 | call_function_interrupt | smp_call_function_interrupt | 函数数据通过call_data_struct传送,cpu会调用该函数 |
0xef | LOCAL_TIMER_VECTOR | APIC定期器中断 | apic_timer_interrupt | smp_apic_timer_interrupt | 触发定时器的软中断 |
0xff | SPURIOUS_APIC_VECTOR | 伪中断 | spurious_interrupt | smp_spurious_interrupt | 忽略 |
0xfe | ERROR_APIC_VECTOR | APIC错误 | error_interrupt | smp_error_interrupt | 打印错误 |
0xfa中断说明:
当cpu需要另一个cpu执行某个函数时,只需要初始化
struct call_data_struct {
void (*func) (void *info);
void *info;
atomic_t started;
atomic_t finished;
int wait;
};
的结构体,然后发出一个0xfa中断即可。
软中断初始化
软中断初始化分为两部分:
- 初始化定时器时,会打开TIMER_SOFTIRQ的软中断,并设置中断处理函数为run_timer_softirq。
- softirq_init函数执行,会打开TASKLET_SOFTIRQ和HI_SOFTIRQ,处理函数分别为 tasklet_action和 tasklet_hi_action。
软中断的线程处理机制就不说了。
Linux x86_64内核中断初始化的更多相关文章
- Linux x86_64 APIC中断路由机制分析
不同CPU体系间的中断控制器工作原理有较大差异,本文是<Linux mips64r2 PCI中断路由机制分析>的姊妹篇,主要分析Broadwell-DE X86_64 APIC中断路由原理 ...
- Linux内核中断学习
1.内核中断概述 (1)在OS环境下编写中断处理函数与之前在裸机中编写中断处理函数的方式是不一样的,在Linux内核中提供了一套用来管理硬件中断资源的软件体系架构. (2)在操作系统中,中断号与gpi ...
- Linux 内核中断内幕
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html#resources Linux 内核中断内幕 ...
- Linux内核中断和异常分析(中)
在linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线.所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,上次讲到单片机的时候,我就讲到了单片机 ...
- Linux驱动技术(六) _内核中断
在硬件上,中断源可以通过中断控制器向CPU提交中断,进而引发中断处理程序的执行,不过这种硬件中断体系每一种CPU都不一样,而Linux作为操作系统,需要同时支持这些中断体系,如此一来,Linux中就提 ...
- Linux 内核中断内幕【转】
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/ 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器.中断分类 ...
- Linux内核中断顶半部和底半部的理解
文章目录 中断上半部.下半部的概念 实现中断下半部的三种方法 软中断 软中断模版 tasklet tasklet函数模版 工作队列 工作队列函数模版 进程上下文和中断上下文 软中断和硬中断的区别 硬中 ...
- linux内核中断之看门狗
一:内核中断 linux内核中的看门狗中断跟之前的裸板的中断差不多,在编写驱动之前,需要线把内核自带的watch dog模块裁剪掉,要不然会出现错误:在Device Drivers /Watchdog ...
- 深入linux kernel内核配置选项
============================================================================== 深入linux kernel内核配置选项 ...
随机推荐
- 序列化Json格式
Json = JsonUtil.Serialize(new { code = 1, msg = "文件删除成功" }); public class JsonUtil { ...
- eclipse和android studio的目录结构分析
不管你喜不喜欢,愿不愿意,自从Google宣布正式停止对于eclipse的支持,要开发android的APP,你都得乖乖的用android studio(以下简称AS)了,不过也不是什么悲伤的故事,对 ...
- OpenStack_I版 6.Neutron部署
Neutron是不能自己创建网络的,它需要借助插件才能创建虚拟网桥.网卡 依赖插件 配置ml2为核心插件 本次网络模型采用扁平化网络,不同的网络类型不同的配置,不同的使用方法 打开安全组功能 Linu ...
- POI 的API大全二
1.POI结构与常用类 (1)POI介绍 Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发 ...
- HttpServletRequest对象
一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象 ...
- 由js深拷贝引起的对内存空间的一些思考
数据类型 js常用数据类型分为基本类型和引用类型 基本类型:null.undefined.数值型.字符串型.布尔型 引用类型:数组.对象 内存空间 var a = [1, 2, 3]; var b = ...
- 都在说RunLoop...... 到底什么是RunLoop?
RunLoop(消息循环):说白了就是一种事件监听循环.就好比是一个while循环,监听到事件就起来,没有就休息. 介绍: 它可以在不同模式下进行切换,iOS有五种模式,其中UIInitializat ...
- java保留小数点后位数以及输出反转数字
//方法一double b = 8.0/3.0; //与C语言不同,此处8.0和8有所区分 String format = String.format("%.2f,b"); //表 ...
- 【Luogu3804】【模板】后缀自动机(后缀自动机)
[Luogu3804][模板]后缀自动机(后缀自动机) 题面 洛谷 题解 一个串的出现次数等于\(right/endpos\)集合的大小 而这个集合的大小等于所有\(parent\)树上儿子的大小 这 ...
- STM32F10x的启动汇编分析
;******************** (C) COPYRIGHT 2009 STMicroelectronics ********************;* File Name ...