xv6-中断和系统调用
Interrupt and System call
xv6 通过一个存放函数指针的数组来作为中断向量表,在 main 函数初始化过程中,调用tvinit 函数完成中断向量表的初始化。tvinit 将每一个中断处理程序的地址写入 idt 数组中,idtinit 将数组地址载入中断向量表寄存器,硬件能够根据中断向量表寄存器准确找出中断处理程序,xv6 使用 vector.pl 脚本生成 vector 数组,vector 数组存放着每个中断处理程序的入口地址,xv6 简单地将所有的中断处理程序指向 alltraps,由 alltraps 来负责具体的处理。在调用 alltraps 之前,xv6 统一压入 errnum 和 trapnum 来区分是 256 情况中的哪种。
void
tvinit(void)
{
int i;
for(i = 0; i < 256; i++)
SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER);
initlock(&tickslock, "time");
}
void
idtinit(void)
{
lidt(idt, sizeof(idt));
}
vector255:
pushl $0
pushl $255
jmp alltrapsalltraps 继续压入寄存器保存现场,得到 trapframe 结构体,trapframe 结构体如图所示,其中 oesp 没有用处,这是 pushal 指令统一压栈的。
.globl alltraps
alltraps:
# Build trap frame.
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushal
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LZY的Code生活!