/* By Marcus Xing kernel/protect.c 有关保护模式的函数 */ #include "type.h" #include "const.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"); */ }