Ver código fonte

:new: 设置了IDT,装载了TSS到GDT中。实现了第一个简易的中断处理函数ignore_int

fslongjin 3 anos atrás
pai
commit
cfd0f76059
3 arquivos alterados com 85 adições e 16 exclusões
  1. 0 14
      kernel/common/font.h
  2. 74 0
      kernel/head.S
  3. 11 2
      kernel/main.c

+ 0 - 14
kernel/common/font.h

@@ -1,17 +1,3 @@
-/***************************************************
-*		版权声明
-*
-*	本操作系统名为:MINE
-*	该操作系统未经授权不得以盈利或非盈利为目的进行开发,
-*	只允许个人学习以及公开交流使用
-*
-*	代码最终所有权及解释权归田宇所有;
-*
-*	本模块作者:	田宇
-*	EMail:		[email protected]
-*
-*
-***************************************************/
 
 #ifndef __FONT_H__
 #define __FONT_H__

+ 74 - 0
kernel/head.S

@@ -53,6 +53,70 @@ entry64:
 
     movq $0xffff800000007e00, %rsp //rsp的地址
 
+setup_IDT:
+    leaq m_ignore_int(%rip),  %rdx // 将ignore_int的地址暂时存到中段描述符的高8B
+    movq $(0x08 << 16), %rax  // 设置段选择子。由IDT结构和段选择子结构可知,本行设置段基地址为0x100000,TI=0,RPL=0
+    movw %dx, %ax
+
+    movq $ (0x8e00 << 32), %rcx // 设置Type=1110 P=1 DPL=00 0=0
+    addq %rcx, %rax
+
+    // 把ignore_int的地址填写到正确位置, rax存低8B, rdx存高8B
+    movl %edx, %ecx
+    shrl $16, %ecx // 去除低16位
+    shlq $48, %rcx
+    addq %rcx, %rax // 填写段内偏移31:16
+
+    shrq $32, %rdx // (已经填写了32位,故右移32)
+
+    leaq IDT_Table(%rip), %rdi // 获取中断描述符表的首地址,存储到rdi
+    mov $256, %rcx  // 初始化每个中断描述符
+
+repeat_set_idt:
+    // ====== 循环,初始化总共256个中断描述符 ===
+    movq %rax, (%rdi)   // 保存低8B
+    movq %rdx, 8(%rdi)  // 保存高8B
+
+    addq $0x10, %rdi // 转到下一个IDT表项
+    dec %rcx
+    jne repeat_set_idt
+
+SetUp_TSS64:
+    // == 设置64位的任务状态段表 ===
+    //rdx保存高8B, rax保存低8B
+    leaq TSS64_Table(%rip), %rdx
+    xorq %rax, %rax
+    xorq %rcx, %rcx
+
+    // 设置TSS描述符的47:40位为1000 1001
+    movq $0x89, %rax
+    shlq $40, %rax
+
+    // 设置段基地址31:24
+    movl %edx, %ecx
+    shrl $24, %ecx
+    shlq $56, %rcx
+    addq %rcx, %rax
+
+    xorq %rcx, %rcx
+
+    // 设置段基地址23:00
+    movl %edx, %ecx
+    andl $0xffffff, %ecx // 清空ecx的中有效值的高8位(也就是上面已经赋值了的)
+    shlq $16, %rcx
+    addq %rcx, %rax
+
+    addq $103, %rax // 设置段长度
+
+    leaq GDT_Table(%rip), %rdi
+    movq %rax, 64(%rdi) // 把低八B存储到GDT第8项
+    shrq $32, %rdx
+    movq %rdx, 72(%rdi) // 高8B存到GDT低9项
+
+    // 装载任务状态段寄存器
+    mov $0x40, %ax // 设置起始地址为64
+    ltr %ax
+
     // 切换到内核主程序
     movq go_to_kernel(%rip), %rax
     pushq $0x08
@@ -62,7 +126,17 @@ entry64:
 go_to_kernel:
     .quad Start_Kernel
 
+// ==== 异常/中断处理模块 ignore int: 忽略中断
+m_ignore_int:
+// 切换到c语言的ignore_int
+    movq go_to_ignore_int(%rip), %rax
+    pushq $0x08
+    pushq %rax
+    lretq
+
 
+go_to_ignore_int:
+    .quad ignore_int
 
 // 初始化页表
 .align 8 //设置为8byte对齐

+ 11 - 2
kernel/main.c

@@ -47,7 +47,6 @@ void test_printk()
     printk("2022-01-01\tDavid\t99\n");
     printk("2022-01-01\tJohn\t95\n");
 
-
     //测试输出八进制
     printk("\nTest base 8 : %d --> %o\n", 255, 255);
 
@@ -62,9 +61,19 @@ void Start_Kernel(void)
     init_printk(1440, 900, FR_address, 1440 * 900 * 4, 8, 16);
 
     show_welcome();
-    test_printk();
+    //test_printk();
     
+    int t = 1 / 0;  // 测试异常处理模块ignore_int能否正常工作
+
+    while (1)
+        ;
+}
 
+void ignore_int()
+{
+    printk("[");
+    printk_color(YELLOW, BLACK, "WARN");
+    printk("] Unknown interrupt or fault at RIP.\n");
     while (1)
         ;
 }