177 lines
5.4 KiB
C
177 lines
5.4 KiB
C
#ifndef MINIOS_PROTECT_H
|
||
#define MINIOS_PROTECT_H
|
||
|
||
#include "type.h"
|
||
|
||
/* 存储段描述符/系统段描述符 */
|
||
typedef struct s_descriptor { /* 共 8 个字节 */
|
||
u16 limit_low; /* Limit */
|
||
u16 base_low; /* Base */
|
||
u8 base_mid; /* Base */
|
||
u8 attr1; /* P(1) DPL(2) DT(1) TYPE(4) */
|
||
u8 limit_high_attr2; /* G(1) D(1) 0(1) AVL(1) LimitHigh(4) */
|
||
u8 base_high; /* Base */
|
||
}DESCRIPTOR;
|
||
|
||
/* 门描述符 */
|
||
typedef struct s_gate
|
||
{
|
||
u16 offset_low; /* Offset Low */
|
||
u16 selector; /* Selector */
|
||
u8 dcount; /* 该字段只在调用门描述符中有效。
|
||
如果在利用调用门调用子程序时引起特权级的转换和堆栈的改变,需要将外层堆栈中的参数复制到内层堆栈。
|
||
该双字计数字段就是用于说明这种情况发生时,要复制的双字参数的数量。 */
|
||
u8 attr; /* P(1) DPL(2) DT(1) TYPE(4) */
|
||
u16 offset_high; /* Offset High */
|
||
}GATE;
|
||
|
||
/* 描述符选择子 */
|
||
#define SELECTOR_DUMMY 0x00 // ┓
|
||
#define SELECTOR_FLAT_C 0x08 // ┣ LOADER 里面已经确定了的.
|
||
#define SELECTOR_FLAT_RW 0x10 // ┃
|
||
#define SELECTOR_VIDEO (0x18+3) // ┛<-- RPL=3
|
||
#define SELECTOR_TSS 0x20 // TSS. 从外层跳到内存时 SS 和 ESP 的值从里面获得.
|
||
#define SELECTOR_LDT 0x28
|
||
/* 描述符类型值说明 */
|
||
#define DA_32 0x4000 /* 32 位段 */
|
||
#define DA_LIMIT_4K 0x8000 /* 段界限粒度为4K字节 */
|
||
#define DA_DPL0 0x00 /* DPL = 0 */
|
||
#define DA_DPL1 0x20 /* DPL = 1 */
|
||
#define DA_DPL2 0x40 /* DPL = 2 */
|
||
#define DA_DPL3 0x60 /* DPL = 3 */
|
||
/* 存储段描述符类型值说明 */
|
||
#define DA_DR 0x90 /* 存在的只读数据段类型值 */
|
||
#define DA_DRW 0x92 /* 存在的可读写数据段属性值 */
|
||
#define DA_DRWA 0x93 /* 存在的已访问可读写数据段类型值*/
|
||
#define DA_C 0x98 /* 存在的只执行代码段属性值 */
|
||
#define DA_CR 0x9A /* 存在的可执行可读代码段属性值 */
|
||
#define DA_CCO 0x9C /* 存在的只执行一致代码段属性值 */
|
||
#define DA_CCOR 0x9E /* 存在的可执行可读一致代码段属性值*/
|
||
/* 系统段描述符类型值说明 */
|
||
#define DA_LDT 0x82 /* 局部描述符表段类型值 */
|
||
#define DA_TaskGate 0x85 /* 任务门类型值 */
|
||
#define DA_386TSS 0x89 /* 可用 386 任务状态段类型值 */
|
||
#define DA_386CGate 0x8C /* 386 调用门类型值 */
|
||
#define DA_386IGate 0x8E /* 386 中断门类型值 */
|
||
#define DA_386TGate 0x8F /* 386 陷阱门类型值 */
|
||
|
||
/* 选择子类型值说明 */
|
||
/* 其中, SA_ : Selector Attribute */
|
||
#define SA_RPL_MASK 0xFFFC
|
||
#define SA_RPL0 0
|
||
#define SA_RPL1 1
|
||
#define SA_RPL2 2
|
||
#define SA_RPL3 3
|
||
|
||
#define SA_TI_MASK 0xFFFB
|
||
#define SA_TIG 0
|
||
#define SA_TIL 4
|
||
|
||
/* 异常中断向量 */
|
||
#define INT_VECTOR_DIVIDE 0x0
|
||
#define INT_VECTOR_DEBUG 0x1
|
||
#define INT_VECTOR_NMI 0x2
|
||
#define INT_VECTOR_BREAKPOINT 0x3
|
||
#define INT_VECTOR_OVERFLOW 0x4
|
||
#define INT_VECTOR_BOUNDS 0x5
|
||
#define INT_VECTOR_INVAL_OP 0x6
|
||
#define INT_VECTOR_COPROC_NOT 0x7
|
||
#define INT_VECTOR_DOUBLE_FAULT 0x8
|
||
#define INT_VECTOR_COPROC_SEG 0x9
|
||
#define INT_VECTOR_INVAL_TSS 0xA
|
||
#define INT_VECTOR_SEG_NOT 0xB
|
||
#define INT_VECTOR_STACK_FAULT 0xC
|
||
#define INT_VECTOR_PROTECTION 0xD
|
||
#define INT_VECTOR_PAGE_FAULT 0xE
|
||
#define INT_VECTOR_COPROC_ERR 0x10
|
||
|
||
/* 外设中断向量,时钟中断,键盘中断等都在这里 */
|
||
#define INT_VECTOR_IRQ0 0x20
|
||
#define INT_VECTOR_IRQ8 0x28
|
||
|
||
/* 权限 */
|
||
#define PRIVILEGE_KRNL 0
|
||
#define PRIVILEGE_TASK 1
|
||
#define PRIVILEGE_USER 3
|
||
|
||
#define RPL_KRNL SA_RPL0
|
||
#define RPL_TASK SA_RPL1
|
||
#define RPL_USER SA_RPL3
|
||
|
||
/* 初始化描述符函数 */
|
||
static void
|
||
init_segment(DESCRIPTOR *p_desc, u32 base, u32 limit, u16 attribute)
|
||
{
|
||
p_desc->limit_low = limit & 0x0FFFF; // 段界限1
|
||
p_desc->base_low = base & 0x0FFFF; // 段基址1
|
||
p_desc->base_mid = (base >> 16) & 0x0FF; // 段基址2
|
||
p_desc->attr1 = attribute & 0xFF; // 属性1
|
||
p_desc->limit_high_attr2 = ((limit >> 16) & 0x0F) | // 段界限2
|
||
((attribute >> 8) & 0xF0); // 属性2
|
||
p_desc->base_high = (base >> 24) & 0x0FF; // 段基址3
|
||
}
|
||
|
||
static void
|
||
init_gate(GATE *p_gate, u8 desc_type, void *handler, u8 privilage)
|
||
{
|
||
p_gate->offset_low = (u32)handler & 0xffff; //中断处理地址的低16位
|
||
p_gate->selector = SELECTOR_FLAT_C; //内核代码段选择子
|
||
p_gate->dcount = 0; //不需要复制参数
|
||
p_gate->attr = desc_type | (privilage << 5); //属性
|
||
p_gate->offset_high = ((u32)handler >> 16) & 0xffff;//中断处理地址的高16位
|
||
}
|
||
|
||
/* GDT 、 LDT 和 IDT 中描述符的个数 */
|
||
#define GDT_SIZE 128
|
||
#define LDT_SIZE GDT_SIZE
|
||
#define IDT_SIZE 256
|
||
|
||
extern DESCRIPTOR gdt[GDT_SIZE];
|
||
extern DESCRIPTOR ldt[LDT_SIZE];
|
||
extern GATE idt[IDT_SIZE];
|
||
|
||
/* TSS(Taskstate) */
|
||
typedef struct s_tss {
|
||
u32 backlink;
|
||
u32 esp0; /* 当发生中断的时候esp就会变成esp0 */
|
||
u32 ss0; /* 当发生中断的时候ss就会变成ss0,由于ss0存储的是内核态权限段,于是顺利进入内核态 */
|
||
u32 esp1;
|
||
u32 ss1;
|
||
u32 esp2;
|
||
u32 ss2;
|
||
u32 cr3;
|
||
u32 eip;
|
||
u32 flags;
|
||
u32 eax;
|
||
u32 ecx;
|
||
u32 edx;
|
||
u32 ebx;
|
||
u32 esp;
|
||
u32 ebp;
|
||
u32 esi;
|
||
u32 edi;
|
||
u32 es;
|
||
u32 cs;
|
||
u32 ss;
|
||
u32 ds;
|
||
u32 fs;
|
||
u32 gs;
|
||
u32 ldt;
|
||
u16 trap;
|
||
u16 iobase; /* I/O位图基址大于或等于TSS段界限,就表示没有I/O许可位图 */
|
||
/*u8 iomap[2];*/
|
||
}TSS;
|
||
|
||
/* 全局的tss数据结构 */
|
||
extern TSS tss;
|
||
|
||
/* 描述符表 */
|
||
struct Pseudodesc {
|
||
u16 pd_lim; // Limit
|
||
u32 pd_base; // Base address
|
||
} __attribute__ ((packed));
|
||
|
||
extern struct Pseudodesc gdt_ptr, idt_ptr;
|
||
|
||
#endif /* MINIOS_PROTECT_H */
|