首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

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

编程知识
2024年08月31日 09:15

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测试了时钟中断。

From:https://www.cnblogs.com/yingyulou/p/18389916
本文地址: http://shuzixingkong.net/article/1603
0评论
提交 加载更多评论
其他文章 NSmartProxy:一款.NET开源、跨平台的内网穿透工具
前言 今天大姚给大家分享一款.NET开源、免费(MIT License)、跨平台的内网穿透工具,采用.NET Core的全异步模式打造:NSmartProxy。 内网穿透工具介绍 内网穿透工具是一种能够允许用户从互联网上的任何地方安全地访问并管理处于内网(如家庭网络、公司局域网等)中的设备的工具。
NSmartProxy:一款.NET开源、跨平台的内网穿透工具 NSmartProxy:一款.NET开源、跨平台的内网穿透工具 NSmartProxy:一款.NET开源、跨平台的内网穿透工具
.Net 5.0 WebAPI 发布至 Linux 系统
本文先安装 .net 5.0 的环境,再创建一个示例项目并发布至 CentOS 上,同时列明了一些注意的点;最后将 dotnet 命令添加到系统自启动服务。
.Net 5.0 WebAPI 发布至 Linux 系统 .Net 5.0 WebAPI 发布至 Linux 系统 .Net 5.0 WebAPI 发布至 Linux 系统
【漏洞分析】OSN 代币攻击事件:一笔资金伪造多个分红大户
背景 OSN 是一种 fee on transfer 代币,会根据用户分红账户的余额对用户发放分红。攻击者利用漏洞增发分红账户的余额,随后触发分红机制完成获利。 OSN:https://bscscan.com/address/0x810f4c6ae97bcc66da5ae6383cc31bd3670
【漏洞分析】OSN 代币攻击事件:一笔资金伪造多个分红大户 【漏洞分析】OSN 代币攻击事件:一笔资金伪造多个分红大户 【漏洞分析】OSN 代币攻击事件:一笔资金伪造多个分红大户
最常用集合 - arraylist详解
ArrayList介绍 ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量(capacity),表示底层数组的实际大小,容器内存储元素的个数不
最常用集合 - arraylist详解 最常用集合 - arraylist详解 最常用集合 - arraylist详解
网络安全公开数据集Maple-IDS,恶意流量检测数据集开放使用!
Maple Dataset 枫叶数据集Maple Dataset枫叶数据集由东北林业大学网络安全实验室(https://maple.nefu.edu.cn/lab/)公开发布,是用于入侵检测评估的数据集,其目的在于提升异常基础入侵检测系统(IDS)以及入侵预防系统(IPS)的性能与可靠性。在网络攻击
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP
​对各高校即将毕业的学子来说,毕业设计算是在大学里的最后一个大作业。特别是软件、计算机、电子等相关专业,毕业设计非常讲究实操,往往要求实现一个实用的、可用的、易用的软件系统或手机APP。 不管是软件还是APP,都要通过编程来实现。对于编程类的毕业设计,既有图书馆管理系统这样万年不变的增删改查软件,也
Session的运行机制
浏览器通过web访问服务器,服务器的web服务开启后,第一步就是开启session,这也是session的第一阶段: session_start() 这个函数的作用:开启session,然后根据以前设置的session_name去读取cookie信息,判断$_Cookies[$session_nam
jenkins动态切换环境
一.代码层实现动态切换 1.首先在conftest.py下声明pytest_addoption钩子函数,写法如下 def pytest_addoption(parser): # 设置要接收的命令行参数 parser.addoption("--env", default=&quot
jenkins动态切换环境 jenkins动态切换环境 jenkins动态切换环境