ucore-lab1-ex6

完善中断初始化和处理

1.中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?

一个表项占8字节,根据 interrupt vector 在 IDT 中找到一个 interrupt gate,根据 gate 的 offset 加上根据 segment selector 在 GDT 中找到的 base 即可得到中断处理程序的入口。

2.请编程完善 kern/trap/trap.c 中对中断向量表进行初始化的函数 idt_init。在 idt_init 函数中,依次对所有中断入口进行初始化。使用 mmu.h 中的 SETGATE 宏,填充 idt 数组内容。每个中断的入口由 tools/vectors.c 生成,使用 trap.c 中声明的 vectors 数组即可。

/* idt_init - initialize IDT to each of the entry points in kern/trap/vectors.S */
void
idt_init(void) {
     /* LAB1 YOUR CODE : STEP 2 */
     /* (1) Where are the entry addrs of each Interrupt Service Routine (ISR)?
      *     All ISR's entry addrs are stored in __vectors. where is uintptr_t __vectors[] ?
      *     __vectors[] is in kern/trap/vector.S which is produced by tools/vector.c
      *     (try "make" command in lab1, then you will find vector.S in kern/trap DIR)
      *     You can use  "extern uintptr_t __vectors[];" to define this extern variable which will be used later.
      * (2) Now you should setup the entries of ISR in Interrupt Description Table (IDT).
      *     Can you see idt[256] in this file? Yes, it's IDT! you can use SETGATE macro to setup each item of IDT
      * (3) After setup the contents of IDT, you will let CPU know where is the IDT by using 'lidt' instruction.
      *     You don't know the meaning of this instruction? just google it! and check the libs/x86.h to know more.
      *     Notice: the argument of lidt is idt_pd. try to find it!
      */
    extern uintptr_t __vectors[];
    int i;
    for(i = 0 ; i < sizeof(idt) / sizeof(struct gatedesc) ; ++ i)
    {
        SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);
    }
    SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);
    lidt(&idt_pd);
}   

需要注意的是一些宏的使用,比如 GD_KTEXT,它的实现在 memlayout.h 中,相当于用由 index 左移三位构造了一个 Kernel 代码段的段选择子。

当然还存在一些问题,

【注意】除了系统调用中断(T_SYSCALL)使用陷阱门描述符且权限为用户态权限以外,其它中断均使用特权级(DPL)为0的中断门描述符,权限为内核态权限;而 ucore 的应用程序处于特权级3,需要采用` int 0x80`指令操作(这种方式称为软中断,软件中断,Tra 中断,在 lab5 会碰到)来发出系统调用请求,并要能实现从特权级3到特权级0的转换,所以系统调用中断(T_SYSCALL)所对应的中断门描述符中的特权级(DPL)需要设置为3。

这里我觉得指导书的意思是写SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);,但是答案里给的是SETGATE(idt[T_SWITCH_TOK], 0, GD_KTEXT, __vectors[T_SWITCH_TOK], DPL_USER);,这段代码应该是后面challenge的代码,但是SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);这段代码不见了还是有些费解。。。

3.请编程完善 trap.c 中的中断处理函数 trap,在对时钟中断进行处理的部分填写 trap 函数中处理时钟中断的部分,使操作系统每遇到 100 次时钟中断后,调用 print_ticks 子程序,向屏幕上打印一行文字”100 ticks”。

真的很简单hhh

static void
trap_dispatch(struct trapframe *tf) {
    char c;

    switch (tf->tf_trapno) {
    case IRQ_OFFSET + IRQ_TIMER:
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        ticks ++;
        if(ticks % TICK_NUM == 0) 
            print_ticks();
        break;
    case IRQ_OFFSET + IRQ_COM1:
        ......
}

最后的结果如下:

注意:这里目前只能打印一堆100 ticks,剩下的部分需要在后面的 challenge 部分完成。指导书上说会响应键盘输入,不知道为啥我这里不行,在 lab1_result 里 make 也不行。

posted @ 2020-08-30 14:01  xinze  阅读(171)  评论(0编辑  收藏  举报