ACPI这个单词,用电脑用多了的同学应该或多或少能在系统的报错信息等地方见过它。它表示表示高级配置和电源管理接口(Advanced Configuration and Power Management Interface)。通过ACPI规范,就能查询计算机硬件的一些信息。
在这里给大家推荐一下我的操作系统项目,希望大家能在GitHub上面给我点个小星星哦~https://github.com/fslongjin/DragonOS
事情的起因是这样的,我在写DragonOS的时候,需要初始化I/O APIC控制器,因此我需要知道I/O APIC控制器的控制寄存器的地址,书上说的方法是查主板芯片手册。但是我在想,难不成我还要把那么多的主板芯片组的手册都查一遍?于是我就找到了ACPI规范,能够通过它来获取电脑的状态信息。这些信息里面就包括了I/O APIC控制寄存器的基地址。
大概的流程是这样的:
首先,根据MultiBoot2协议,我们能从BootLoader那里获取到一份RSDP的拷贝。接着,就可以去解析这个RSDP,RSDP内包含了RSDT的物理地址。于是,我们将RSDT的物理地址填写进页表之中,接着去访问RSDT。
看到这里,读者可能会疑惑了,在内存管理结构中不是已经映射了虚拟内存页面吗?怎么现在又多了这个物理地址需要映射?
原因是,内存管理结构中,我们并没有将所有的物理地址都映射了。还有一部分是系统保留的内存地址以及设备的寄存器物理地址。这里的就属于由BootLoader保留的物理地址,因此,在内存管理单元中并没有映射它们。
根据ACPI规范,RSDT的结构是这样的:
然后,我们就可以根据Entry数组中的物理地址,一个个的查找我们需要的数据结构。这时,我们仍然需要在页表中映射这些地址。经过我的观察,这些物理地址是连续的,且包含在同一个2MB物理页中,因此只需要映射一个物理页即可。
然后,根据ACPI规范,我们可以看到,这个Entry指向了多种数据结构,如APIC、HPET等。它们这些数据结构的共同特点就是,开头部分都是Signature+length的结构,我们可以根据signature来识别每个Entry项对应的数据结构,然后再用合适的结构体来解析它们。
Entry中可能包含的部分数据结构(因物理平台而异)
关于我们目标的APIC的信息,就位于表格中的Signature为APIC的数据结构中。这个数据结构叫做MADT(Multiple APIC Description Table),进一步查阅ACPI文档,看到了MADT的结构,如下所示:
这里面就包含了本地中断控制器的地址,但是这并不是I/O APIC的控制寄存器的地址。再继续查找文档,看到Interrupt Controller Structure的部分内容如下:
其中,I/O APIC的数据结构中,就有我们需要的I/O APIC控制寄存器的物理地址。
这里面还包含了Globan System Intrrupt Base,这对于我们的操作系统编程也是一个有用的信息。
到这里,我们的最开始的目标就达成了!成功查询到了I/O APIC控制寄存器的物理地址。
转载请注明来源:https://longjin666.top/?p=1361