- /*
- By Marcus Xing
- kernel/protect.c
- 有关保护模式的函数
- */
- #include "type.h"
- #include "const.h"
- #include "ipc.h"
- #include "protect.h"
- #include "proc.h"
- #include "console.h"
- #include "tty.h"
- #include "global.h"
- #include "proto.h"
- /* 内中断处理函数声明 */
- void Divide_Error();
- void Single_Step_Exception();
- void NMI();
- void Breakpoint_Exception();
- void Overflow();
- void Bounds_Check();
- void Inval_Opcode();
- void Copr_Not_Available();
- void Double_Fault();
- void Copr_Seg_Overrun();
- void Inval_TSS();
- void Segment_Not_Present();
- void Stack_Exception();
- void General_Protection();
- void Page_Fault();
- void Copr_Error();
- /* 外中断处理函数声明 */
- void hw_00();
- void hw_01();
- void hw_02();
- void hw_03();
- void hw_04();
- void hw_05();
- void hw_06();
- void hw_07();
- void hw_08();
- void hw_09();
- void hw_10();
- void hw_11();
- void hw_12();
- void hw_13();
- void hw_14();
- void hw_15();
- /*----------------------------------------------------------------------Init_GDT
- 此函数用于初始化GDT
- */
- void Init_GDT()
- {
- /* 填充GDT */
- Fill_Desc(0,0,0,0); /* DUMMY段,这个必须有 */
- Fill_Desc(1,0,0xfffff,DA_DRW + DA_32 + DA_LIMIT_4K); /* 平坦4G 32位代码段 */
- Fill_Desc(2,0,0xfffff,DA_C + DA_32 + DA_LIMIT_4K); /* 平坦4G 32位数据段 */
- Fill_Desc(3,0xb8000,0xffff,DA_DRW + DA_DPL3); /* 视频段描述符,DPL为3 */
- Fill_Desc(126,0,0xfffff,DA_C + DA_LIMIT_4K); /* 16位平坦代码段描述符 */
- Fill_Desc(127,0,0xffff,DA_DRW); /* NORMAL描述符,跳回PM用*/
- /* 填充GDT_Ptr */
- u16 *p16_GDT_Ptr_Len = (u16 *)GDT_Ptr;
- u32 *p32_GDT_Ptr_Base = (u32 *)(GDT_Ptr + 2);
- *p16_GDT_Ptr_Len = (u16)(sizeof(Descriptor) * GDT_SIZE - 1);
- *p32_GDT_Ptr_Base = (u32)GDT;
- }
- /*----------------------------------------------------------------------Init_IDT
- 此函数用于初始化IDT
- */
- void Init_IDT()
- {
- /* 初始化系统内中断描述符 */
- Fill_Gate(INT_VECTOR_DIVIDE,Divide_Error,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_DEBUG,Single_Step_Exception,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_NMI,NMI,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_BREAKPOINT,Breakpoint_Exception,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_OVERFLOW,Overflow,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_BOUNDS,Bounds_Check,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_INVAL_OP,Inval_Opcode,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_COPROC_NOT,Copr_Not_Available,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_DOUBLE_FAULT,Double_Fault,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_COPROC_SEG,Copr_Seg_Overrun,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_INVAL_TSS,Inval_TSS,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_SEG_NOT,Segment_Not_Present,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_STACK_FAULT,Stack_Exception,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_PROTECTION,General_Protection,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_PAGE_FAULT,Page_Fault,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_COPROC_ERR,Copr_Error,DA_386IGate,PRIVILEGE_KRNL);
- /* 填充IDT_Ptr */
- u16 *p16_IDT_Ptr_Len = (u16 *)IDT_Ptr;
- u32 *p32_IDT_Ptr_Base = (u32 *)(IDT_Ptr + 2);
- *p16_IDT_Ptr_Len = sizeof(Gate) * IDT_SIZE - 1;
- *p32_IDT_Ptr_Base = (u32)IDT;
- /* 填充外中断的中断描述符 */
- Fill_Gate(INT_VECTOR_IRQ0 + 0,hw_00,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 1,hw_01,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 2,hw_02,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 3,hw_03,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 4,hw_04,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 5,hw_05,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 6,hw_06,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 7,hw_07,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 8,hw_08,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 9,hw_09,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 10,hw_10,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 11,hw_11,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 12,hw_12,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 13,hw_13,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 14,hw_14,DA_386IGate,PRIVILEGE_KRNL);
- Fill_Gate(INT_VECTOR_IRQ0 + 15,hw_15,DA_386IGate,PRIVILEGE_KRNL);
- /* 系统调用的中断入口 */
- Fill_Gate(SYSTEM_CALL_INT_VECTOR,System_Call,DA_386IGate,PRIVILEGE_USER);
- }
- /*---------------------------------------------------------------------Fill_Desc
- 此函数用于填充GDT的描述符
- para1:要填充的描述符在GDT的索引,从0开始,以1递增
- para2:要填充的描述符的基地址
- para3:要填充的描述符的段界限
- para4:要填充的描述符的段属性
- */
- void Fill_Desc(u8 desc_no,u32 base,u32 limit,u16 attr)
- {
- Descriptor *p_Desc = (Descriptor *)&GDT[desc_no];
- p_Desc->limit_low = limit & 0xffff;
- p_Desc->base_low = base & 0xffff;
- p_Desc->base_mid = (base >> 16) & 0xff;
- p_Desc->attr1 = attr & 0xff;
- p_Desc->limit_high_attr2 = ((limit >> 16) & 0xf) | (attr >> 8);
- p_Desc->base_high = (base >> 24) & 0xff;
- }
- /*---------------------------------------------------------------------Fill_Gate
- 此函数用于填充一个IDT中的门描述符
- para1:要填充的描述符在IDT的索引,从0开始,以1递增
- para2:处理程序的地址,即为函数指针,类型在type.h中定义
- para3:门描述符的类型
- para4:门描述符的特权级
- */
- void Fill_Gate(u8 idt_no,Int_Handler handler,u8 type,u8 privilege)
- {
- Gate *p_Gate = (Gate*)&IDT[idt_no];
- u32 base = (u32)handler;
- p_Gate->offset_low = base & 0xffff;
- p_Gate->selector = 16; /* 处理程序的段地址,GDT中的第3个描述符,即FLAT_C */
- p_Gate->dcount = 0;
- p_Gate->attr = type | (privilege << 5);
- p_Gate->offset_high = (base >> 16) & 0xffff;
- }
- /*-------------------------------------------------------------Exception_Handler
- 此函数用来统一处理内中断处理函数,把各个参数打印出来
- para1:中断向量号
- para2:错误码(如果没有,则为0xffffffff)
- para3:出现错误的代码时的EIP
- para4:出现错误的代码时的CS
- para5:出现错误的代码时的EFLAGS
- */
- void Exception_Handler(unsigned int vec_no,int err_code,int eip,int cs,int eflags)
- {
- int i;
- /* 前5行清空,通过改动d_Disp_Pos的值 */
- d_Disp_Pos = 0;
- for(i = 0;i < 80 * 5;i++) /* 每行80个字符 */
- {
- Disp_Str(" ");
- }
- d_Disp_Pos = 0;
- /* 打印各项的值 */
- Disp_Str("Exception! --> ");
- Disp_Str("VEC_NO:");
- Disp_Int(vec_no);
- Disp_Str("/n");
- Disp_Str("CS:");
- Disp_Int(cs);
- Disp_Str("/n");
- Disp_Str("EIP:");
- Disp_Int(eip);
- Disp_Str("/n");
- Disp_Str("EFLAGS:");
- Disp_Int(eflags);
- Disp_Str("/n");
- /* 如果有错误码,则打印之 */
- if(err_code != 0xffffffff)
- {
- Disp_Str("ERROR_CODE:");
- Disp_Int(err_code);
- Disp_Str("/n");
- }
- }
- /*--------------------------------------------------------------Hard_Int_Handler
- 外中断统一的处理函数
- para1:外中断的向量号
- 暂时放空
- */
- void Hard_Int_Handler(int hw_vec_no)
- { /*
- int i;
- 前5行清空,通过改动d_Disp_Pos的值
- d_Disp_Pos = 0;
- for(i = 0;i < 80 * 5;i++) 每行80个字符
- {
- Disp_Str(" ");
- }
- d_Disp_Pos = 0;
- 打印相应的向量号
- Disp_Str("HARD WARE VECTOR:");
- Disp_Int(hw_vec_no);
- Disp_Str("/n");
- */
- }