add 08_Interrupt/11

This commit is contained in:
weidongshan
2021-06-26 14:39:14 +08:00
parent 19005cf6f9
commit f17bb1b04f
21 changed files with 380 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
## 异常向量表的安装与调用
### 1. 回顾中断的发生、处理过程
* 中断发生的硬件过程
![image-20210626114958795](pic/08_Interrupt/060_interrupt_flow.png)
* 中断处理的软件处理流程
* CPU执行完当前指令检查到发生了中断跳到向量表
* 保存现场、执行GIC提供的处理函数、恢复现场
### 2. 异常向量表的安装
#### 2.1 复制向量表
* 汇编代码
```c
// arch\arm\kernel\head.S
1. bl __lookup_processor_type
......
2. bl __create_page_tables
3. ldr r13, =__mmap_switched
4. b __enable_mmu
b __turn_mmu_on
mov r3, r13
ret r3
5. __mmap_switched: // arch\arm\kernel\head-common.S
6. b start_kernel
```
* 复制向量表
```c
start_kernel // init\main.c
setup_arch(&command_line); // arch\arm\kernel\setup.c
paging_init(mdesc); // arch\arm\mm\mmu.c
devicemaps_init(mdesc); // arch\arm\mm\mmu.c
vectors = early_alloc(PAGE_SIZE * 2); // 1.分配新向量表
early_trap_init(vectors); // 2.从代码把向量表复制到新向量表
// 3. 映射新向量表到虚拟地址0xffff0000
/*
* Create a mapping for the machine vectors at the high-vectors
* location (0xffff0000). If we aren't using high-vectors, also
* create a mapping at the low-vectors virtual address.
*/
map.pfn = __phys_to_pfn(virt_to_phys(vectors));
map.virtual = 0xffff0000;
map.length = PAGE_SIZE;
#ifdef CONFIG_KUSER_HELPERS
map.type = MT_HIGH_VECTORS;
#else
map.type = MT_LOW_VECTORS;
#endif
create_mapping(&map);
```
![image-20210626120817244](pic/08_Interrupt/061_copy_vectors.png)
#### 2.2 向量表在哪
上面代码中可以看到代码中向量表位于`__vectors_start`,它在`arch/arm/kernel/vmlinux.lds`中定义:
```shell
__vectors_start = .;
.vectors 0xffff0000 : AT(__vectors_start) {
*(.vectors)
}
. = __vectors_start + SIZEOF(.vectors);
__vectors_end = .;
__stubs_start = .;
.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
*(.stubs)
}
```
在代码里搜`.vectors`,可以找到向量表:
![image-20210626124004537](pic/08_Interrupt/062_vectors_in_source.png)
### 3. 中断向量
发生中断时CPU跳到向量表去执行`b vector_irq`
vector_irq函数使用宏来定义
![image-20210626125245059](pic/08_Interrupt/063_vector_irq.png)
### 4. 处理流程
![image-20210626130003359](pic/08_Interrupt/064_handle_irq.png)
### 5. 处理函数
![image-20210626130412855](pic/08_Interrupt/065_irq_handler.png)

View File

@@ -0,0 +1,81 @@
## GIC驱动程序分析
参考资料:
* [linux kernel的中断子系统之GIC代码分析](http://www.wowotech.net/irq_subsystem/gic_driver.html)
### 1. 回顾
### 2. 函数调用过程
```c
start_kernel (init\main.c)
init_IRQ (arch\arm\kernel\irq.c)
irqchip_init (drivers\irqchip\irqchip.c)
of_irq_init (drivers\of\irq.c)
desc->irq_init_cb = match->data;
ret = desc->irq_init_cb(desc->dev,
desc->interrupt_parent);
```
#### 2.1 platform_driver支持多个device
按照设备树的套路驱动程序注册platform_driver它的of_match_table里有多个of_device_id表示能支持多个设备。
有多种版本的GIC在内核为每一类GIC定义一个结构体of_device_id并放在一个段里
```c
// drivers\irqchip\irq-gic.c
IRQCHIP_DECLARE(gic_400, "arm,gic-400", gic_of_init);
IRQCHIP_DECLARE(arm11mp_gic, "arm,arm11mp-gic", gic_of_init);
IRQCHIP_DECLARE(arm1176jzf_dc_gic, "arm,arm1176jzf-devchip-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
```
把宏`IRQCHIP_DECLARE`展开:
```c
// include\linux\irqchip.h
#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
#define OF_DECLARE_2(table, name, compat, fn) \
_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
#define _OF_DECLARE(table, name, compat, fn, fn_type) \
static const struct of_device_id __of_table_##name \
__used __section(__##table##_of_table) \
= { .compatible = compat, \
.data = (fn == (fn_type)NULL) ? fn : fn }
```
展开示例:
```c
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
static const struct of_device_id __of_table_cortex_a7_gic \
__used __section(__irqchip_of_table) \
= { .compatible = "arm,cortex-a7-gic", \
.data = gic_of_init }
```
#### 2.2 没有定义platform_driver但是套路一样
`drivers\irqchip\irqchip.c`中并没有定义一个platform_driver但是套路是一样的。
![image-20210626083319383](pic/08_Interrupt/058_irqchip_init.png)
调用过程:
![image-20210626084850583](pic/08_Interrupt/059_gic_init.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB