首页 > 编程语言 >一个操作系统的设计与实现——第21章 高级可编程中断控制器

一个操作系统的设计与实现——第21章 高级可编程中断控制器

时间:2024-08-31 10:15:08浏览次数:8  
标签:控制器 21 中断 处理函数 64 APIC 可编程 CPU 时钟

21.1 什么是高级可编程中断控制器

我们已经使用过型号为8259A的可编程中断控制器(Programmable Interrupt Controller,PIC)。在单CPU计算机中,中断的处理相对简单:所有的外设和CPU都连接在PIC上即可。然而,如果计算机中不止一个CPU,情况就会变得复杂起来。以双CPU为例:

  • 键盘中断会被每个CPU分别接收一次,这是错误的
  • 时钟中断会统一广播给各个CPU,这样做虽然没有错误,但降低了灵活性

高级可编程中断控制器(Advanced Programmable Interrupt Controller,APIC)用于解决上述问题。顾名思义,APIC是PIC的升级版,其结构如下:

  • 既然每个CPU需要独立的接收中断,尤其是时钟中断,那就为每个CPU分别安装一个中断控制器,这些APIC就称为本地APIC(Local APIC,LAPIC)。并且,每个LAPIC中都安装了独立的定时器
  • 既然某些外设不能广播到每个CPU上,那就再为外设专门准备一个中断控制器,这个APIC就称为IO APIC
  • 任意两个APIC之间都可以通信。也就是说,不仅CPU与外设之间能够使用中断,CPU之间也能互相使用中断

需要注意的是:PIC和APIC在计算机中是并存的,且均与CPU连接。如果要使用APIC,就需要屏蔽PIC的所有信号。IO APIC的所有信号在默认状态下都是屏蔽的。

21.2 APIC内存映射

APIC使用内存映射而非IO端口进行通信,这类似于显卡。具体来说:

  • LAPIC的内存映射起始地址为0xfee00000,大小为2M
  • IO APIC的内存映射起始地址为0xfec00000,大小为2M
  • APIC中的每个寄存器都是32位的

这两个地址均为物理地址,因此,想要在分页模式下使用APIC,就需要为这两个物理地址安装虚拟地址映射。由于需要映射的地址范围均为2M,因此刚好可以使用2M大页模式。此外,CPU要求这些地址映射是禁用缓存的,将各类页表项的第4位置1即可禁用缓存。

综上,在我们的操作系统中,APIC内存映射的实现如下:

  • 0xfec00000映射到0xffff8000fec00000,使用2M大页模式,禁用缓存
  • 0xfee00000映射到0xffff8000fee00000,使用2M大页模式,禁用缓存

21.3 LAPIC定时器

LAPIC定时器可向其对应的CPU发送时钟中断信号,其通过三个内存地址进行设定:

  1. 0xfee00320:固定设为0x20000 | 时钟中断向量号。在我们的操作系统中,时钟中断向量号为0x20
  2. 0xfee003e0:设定分频器。在我们的操作系统中,固定设为0xb,表示1分频。这里的1表示CPU每经过1个时钟周期,定时器的值就会减1,也就是说,如果将这个1改成比较大的数字,定时器就会变慢,从而能够记录更长的时间
  3. 0xfee00380:设定定时器的初始值。在我们的操作系统中,固定设为0xffff。当定时器的值降为0时,就会触发一次时钟中断,然后将定时器重置到初始值。也就是说,定时器的初值越小,时钟中断的触发频率就越高

21.4 LAPIC中断响应信号

与8259A一样,中断处理函数需要向LAPIC发送中断响应信号。这一过程很简单:向0xfee000b0写入0即可。

21.5 64位中断门与IDT

中断门中存放着中断处理函数的地址,因此,在64位模式下,中断门需要拓展,以存放64位的地址。不过,这一拓展是非常简单的,如下图所示:

也就是说,64位中断门只需要在32位中断门的基础上增加8字节即可,其中,前4字节是中断处理函数的高32位,后4字节是0。

64位的IDTR与GDTR一样,也使用2 + 8 == 10字节内存。

21.6 64位中断

64位中断的发生过程与32位基本一致,但有一个很重要的区别:无关乎特权级是否改变,中断时都会依次压栈ss, rsp, rflags, cs, rip;中断返回时都会出栈这五个寄存器。

21.7 打开时钟中断

请看本章代码21/Mbr.s

第51行,为APIC安装PDPTE,其指向0x91000处的页目录表。

第54~55行,为APIC安装PDE。使用2M大页模式,并禁用缓存。

以上代码中使用的0x1010180x91fb00x91fb8这些地址,均可由二进制计算器计算得到,这里不再赘述。

接下来,请看本章代码21/Int.h

第3行,声明了intInit函数。

接下来,请看本章代码21/Int.hpp

第6行,声明了中断处理函数表。该表由汇编语言定义。

第7行,定义了IDT。IDT中一共有0x20 + 0x2 == 0x22个中断门,前0x20个是CPU要求的,后0x2个是我们的操作系统定义的,每个中断门的大小为16字节。

__picInit函数用于屏蔽8259A主片的所有信号。由于从片是接在主片的2号接口上的,故从片也会被屏蔽。

__apicInit函数用于设定LAPIC定时器。

__idtInit函数用于安装IDT与IDTR。

intInit函数是主函数。

接下来,请看本章代码21/Int.s

第9~52行,定义了0x0 ~ 0x1f号中断的处理函数。

intTimer函数是时钟中断处理函数。

第56~70行,执行"pusha"指令。由于没有64位版本的pusha指令,故只能这样逐个写。

第72~73行,向LAPIC发送中断响应信号。

第75~76行,在每次进入时钟中断时打印一个字符6。

第78~92行,执行"popa"指令。由于没有64位版本的popa指令,故只能这样逐个写。

在时钟中断处理函数中压栈、出栈所有的通用寄存器是为任务切换做准备。64位模式下数据段寄存器已经没有用了,故无需压栈。

第94行,执行iretq指令,从中断返回。注意:这里不能简写为iret,这是因为iretiretq指令在64位CPU中是并存的,前者用于返回到兼容模式代码段。

第96~130行,定义中断处理函数表。第0x21个中断处理函数保留给后续章节使用。

第132~133行,定义通用中断处理函数使用的格式字符串。

21.8 编译与测试

本章代码21/Makefile增加了Int.s的编译与链接命令。

本章代码21/Kernel.c测试了时钟中断。

标签:控制器,21,中断,处理函数,64,APIC,可编程,CPU,时钟
From: https://www.cnblogs.com/yingyulou/p/18389916

相关文章

  • Mint21配置固定IP不生效
    rambo@p360:~$ipashenp6s02:enp6s0:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscfq_codelstateUPgroupdefaultqlen1000link/etherc8:5b:76:82:24:c0brdff:ff:ff:ff:ff:ffinet192.168.2.104/24brd192.168.2.255scopeglobaldynami......
  • Versal 自适应 SoC,XCVM2502-1MSEVSVC2197、XCVM2502-1LSEVSVC2197、XCVM2502-1LLIVSVI
    Prime 系列概述VersalPrime系列是一款高度集成、多核、异构计算平台,适用于数据中心网络、存储和有线通信等多种应用。它通过在优化了连接性的设备中实现低延迟的内联加速,为这些应用提供突破性的性能。 应用:存储加速数据中心网络加速5GxHaul无源光网络通......
  • 基于CW2217B的库仑计硬件设计
    一、CW2217简介:        CW2217B是一款适用于穿戴设备的超低功耗锂电池电量计芯片。芯片监测电池在充放电状态下的电压,电流和温度,运行专利“FastCali”电量计算法,结合电池建模信息,可准确计算电池的剩余电量。CW2217B适用于包括锂锰,锂钴和聚合物等多种类型的锂电池应用......
  • Project 2021图文安装教程及下载
    MicrosoftProject是一个国际上享有盛誉的通用的项目管理工具软件,凝集了许多成熟的项目管理现代理论和方法,可以帮助项目管理者实现时间、资源、成本的计划、控制。MicrosoftProject不仅可以快速、准确地创建项目计划,而且可以帮助项目经理实现项目进度、成本的控制、分析和预......
  • UVA12421 (Jiandan) Mua (I) - Lexical Analyzer题解
    没什么废话、超级珂爱的大模拟。本蒟蒻写了2h才过。其实就是按题意模拟即可,不需要什么高深的算法。本人就是错在了符号中的“=”,因为如果是连续的两个等于号,只能输出“==”,而不能输出“=”“==”,然后本人就卡在这个地方卡了1.5h。代码量也不大,主要是毒瘤细节模拟题。......
  • 世微 AP9195 7-24V 大功率升压恒流驱动芯片 LED照明与控制器方案
    概述AP9195是一款高效率、高精度的升压型大功率LED灯恒流驱动控制芯片。AP9195内置高精度误差放大器,固定关断时间控制电路,恒流驱动电路等,特别适合大功率、多个高亮度LED灯串的恒流驱动。AP9195通过调节外置的电流采样电阻,能控制高亮度LED灯的驱动电流,使LED灯亮......
  • 20240827_102109 python 字符流遍历得到每一行的数据
    需求python字符流遍历得到每一行的数据读取文件的内容每隔一秒钟,显示一行内容示例1示例2......
  • CSP-J 2021 初赛试题解析(第三部分:完善程序(2))
    完善程序二完整程序代码#include<iostream>usingnamespacestd;structpoint{intx,y,id;};boolequals(pointa,pointb){returna.x==b.x&&a.y==b.y;}boolcmp(pointa,pointb){returna.x!=b.x?a.x<b.x:a.y<b.y;}......
  • huawei0821笔试第二题笔记:双端队列deque
    intsolve(deque<int>machines,constvector<int>&tasks){for(inttask:tasks){intcnt=0;//首件不匹配while(cnt<machines.size()&&task!=machines.front()){machines.push_back(machines.......
  • P9041 [PA2021] Fiolki 2
    简要题意可以去看其他题解。前置知识:LGV引理。看到这道题我们先考虑该怎么判定\(f(l,r)\)是否等于\(x\)。看完题面后很难不让人想到LGV引理(不相交路径,起点集\(S\)和终点集\(T\))。但是LGV引理是用于计数的,放在这里似乎并不好用。但是我们可以注意到,只要没有合法情况,......