Xv6内核分析(三.3)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月20日15:57:01 评论 599

main函数之lapicinit

x86的中断体系可参考下面博客:

https://blog.csdn.net/jiangwei0512/article/details/52964339。

1. 设置lapic寄存器

通过mp.c中的mpinit取得mp配置表头后,可以从其中获取lapic寄存器的起始地址,记录在lapic这个全局变量中。lapic寄存器的描述可以在Intel开发手册第三卷第10章找到:

Xv6内核分析(三.3)

lapic寄存器空间总共有4KB大小,被映射到0xFEE00000开始的物理地址空间:

Xv6内核分析(三.3)

访问lapic寄存器时,寄存器的地址必须是16字节对齐的,每次访问一般是4字节访问:

Xv6内核分析(三.3)

lapic寄存器设置函数lapicw如下:

Xv6内核分析(三.3)

由于lapic寄存器每次读写需要4字节操作,所以lapic是一个4字节指针:

Xv6内核分析(三.3)

同时,寄存器的偏移需要除以4,用作lapic数组的下标来访问寄存器:

Xv6内核分析(三.3)

1.2 lapicinit函数

1.2.1 设置SVR寄存器

SVR寄存器的描述如下:

Xv6内核分析(三.3)

xv6设置了APIC software和spurious vector这两个位域:

Xv6内核分析(三.3)

可以看出,xv6使能了apic,vector域的数值如下:

Xv6内核分析(三.3)

在x86体系中,中断向量0~31已经被intel使用,用户自定义的向量号从32~255。从上图中可以看出,xv6的硬件中断向量是从32开始的,由此可以计算出伪中断向量值为32+31=63。

至于IRQ_SPURIOUS值为何是31,也许这是随便定义的,只要不和其他的冲突就行????

1.2.2 设置lapic定时器

Xv6内核分析(三.3)

在每个lapic中有自己的定时器,其时钟源是系统总线的频率,然后经过分频得来:

Xv6内核分析(三.3)

TDCR寄存器就是设置分频值的,具体描述如下:

Xv6内核分析(三.3)

在xv6中,设置的值是X1:

Xv6内核分析(三.3)

对着寄存器描述可知,分频值设置的是1。接着设置LVT timer寄存器,这个寄存器用于设置lapic timer的中断向量号:

Xv6内核分析(三.3)

 

xv6中设置了timer mode和vector两个位域,通过代码可知,timer mode被设置为了periodic,也就是周期产生中断模式,中断向量号被设置为了T_IRQ0 + IRQ_TIMER,也就是32+0=32:

Xv6内核分析(三.3)

最后设置定时器初始计数值寄存器TICR:

Xv6内核分析(三.3)

 

Xv6内核分析(三.3)

当定时器启动的时候,硬件上会递减此数值,减到0时会产生中断。

总结定时器初始化干的工作:

  • 设置分频值为1。
  • 设置定时器工作模式为周期性中断,中断向量号为32。
  • 设置初始的count值为10000000,当设置了一个不为0的数值,timer就启动了???

Xv6内核分析(三.3)

1.2.3 屏蔽LINT0和LINT1中断

在使用Symmetric I/O Mode下的x86中断框架:

Xv6内核分析(三.3)

需要说明的是LINT0和LINT1这两个寄存器,它们对应到Local APIC模块的INTR和NMI引脚,外部的中断会引发这两个寄存器的中断发起。这两个寄存器的具体描述:

Xv6内核分析(三.3)

xv6中的设置代码如下:

Xv6内核分析(三.3)

可以看出,在xv6中是不打算使用这两种中断的。

1.2.4 禁用性能计数器溢出中断

Xv6内核分析(三.3)

首先检查lapic version寄存器的Max LVT Entry位域:

Xv6内核分析(三.3)

Xv6内核分析(三.3)

如果此数值大于等于4,表示当前cpu支持性能计数中断,否则不支持。如果支持,则操作PCINT寄存器屏蔽此中断:

Xv6内核分析(三.3)

1.2.5 设置error中断号

Xv6内核分析(三.3)

中断号的值为32+19=51:

Xv6内核分析(三.3)

ERROR寄存器的描述如下:

Xv6内核分析(三.3)

1.2.6 清除ESR寄存器

Xv6内核分析(三.3)

ESR寄存器的描述如下:

Xv6内核分析(三.3)

Xv6内核分析(三.3)

由描述可知,向此寄存器写值可以更新错误寄存器的状态,所以连续写两次寄存器就相当于清除状态寄存器了。另外此寄存器时可读的,但是读之前必须要先写此寄存器。

1.2.7 写EOI寄存器以响应中断结束

Xv6内核分析(三.3)

写EOI表示中断服务程序结束,EOI寄存器描述如下:

Xv6内核分析(三.3)

1.2.8 设置IPI中断属性

设置ICR中断命令寄存器,从而设置IPI中断属性:

Xv6内核分析(三.3)

ICR寄存器是用来设置核间中断(IPI)的属性的:

Xv6内核分析(三.3)

通过代码可知在xv6中的设置如下:

  • Delivery Mode设置为INIT。
  • Trigger Mod设置的是level。
  • Destination Shorthand设置的是All Including Self。

当设置的是INIT模式时,vector位域必须是0:

Xv6内核分析(三.3)

Destination Field设置为了0,其实这个位域只在Destination Shorthand为0时才用到:

Xv6内核分析(三.3)

同样的,当用INIT模式时,level必须是0:

Xv6内核分析(三.3)

设置完ICR寄存器后,然后等待Delivery Status为空闲状态。

1.2.9 设置TPR任务优先级

Xv6内核分析(三.3)

TPR寄存器的描述如下:

Xv6内核分析(三.3)

lapicinit所做的工作总结:

  • 使能伪中断,并设置中断向量。
  • 设置定时器中断。
  • 屏蔽LINT0、LINT1、性能计数中断。
  • 设置ERROR中断。
  • 设置IPI核间中断。

gewenbin
  • 本文由 发表于 2020年12月20日15:57:01
  • 转载请务必保留本文链接:http://www.databusworld.cn/9296.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: