1 /**
2  * @file gate.h
3  * @author longjin
4  * @brief 门定义
5  * @date 2022-01-24
6  *
7  */
8 
9 #ifndef __GATE_H__
10 #define __GATE_H__
11 
12 #include <common/kprint.h>
13 #include <mm/mm.h>
14 
15 #pragma GCC push_options
16 #pragma GCC optimize("O0")
17 //描述符表的结构体
18 struct desc_struct
19 {
20     unsigned char x[8];
21 };
22 
23 //门的结构体
24 struct gate_struct
25 {
26     unsigned char x[16];
27 };
28 
29 extern struct desc_struct GDT_Table[]; // GDT_Table是head.S中的GDT_Table
30 extern struct gate_struct IDT_Table[]; // IDT_Table是head.S中的IDT_Table
31 //extern unsigned int TSS64_Table[26];
32 
33 struct gdtr
34 {
35     uint16_t size;
36     uint64_t gdt_vaddr;
37 }__attribute__((packed));
38 
39 struct idtr
40 {
41     uint16_t size;
42     uint64_t idt_vaddr;
43 }__attribute__((packed));
44 
45 /**
46  * @brief 初始化中段描述符表内的门描述符(每个16B)
47  * @param gate_selector_addr IDT表项的地址
48  * @param attr P、DPL、TYPE的属性
49  * @param ist 中断栈表号
50  * @param code_addr 指向中断服务程序的指针的地址
51  */
52 
set_gate(ul * gate_selector_addr,ul attr,unsigned char ist,ul * code_addr)53 void set_gate(ul *gate_selector_addr, ul attr, unsigned char ist, ul *code_addr)
54 {
55     ul __d0 = 0, __d1 = 0;
56     ul tmp_code_addr = *code_addr;
57     __d0 = attr << 40; //设置P、DPL、Type
58 
59     __d0 |= ((ul)(ist) << 32); // 设置ist
60 
61     __d0 |= 8 << 16; //设置段选择子为0x1000
62 
63     __d0 |= (0xffff & tmp_code_addr); //设置段内偏移的[15:00]
64 
65     tmp_code_addr >>= 16;
66     __d0 |= (0xffff & tmp_code_addr) << 48; // 设置段内偏移[31:16]
67 
68     tmp_code_addr >>= 16;
69 
70     __d1 = (0xffffffff & tmp_code_addr); //设置段内偏移[63:32]
71 
72     *gate_selector_addr = __d0;
73     *(gate_selector_addr + 1) = __d1;
74 }
75 
76 #define _set_gate(gate_selector_addr, attr, ist, code_addr)                                                 \
77     do                                                                                                      \
78     {                                                                                                       \
79         unsigned long __d0, __d1;                                                                           \
80         __asm__ __volatile__("movw	%%dx,	%%ax	\n\t"                                                         \
81                              "andq	$0x7,	%%rcx	\n\t"                                                        \
82                              "addq	%4,	%%rcx	\n\t"                                                          \
83                              "shlq	$32,	%%rcx	\n\t"                                                         \
84                              "addq	%%rcx,	%%rax	\n\t"                                                       \
85                              "xorq	%%rcx,	%%rcx	\n\t"                                                       \
86                              "movl	%%edx,	%%ecx	\n\t"                                                       \
87                              "shrq	$16,	%%rcx	\n\t"                                                         \
88                              "shlq	$48,	%%rcx	\n\t"                                                         \
89                              "addq	%%rcx,	%%rax	\n\t"                                                       \
90                              "movq	%%rax,	%0	\n\t"                                                          \
91                              "shrq	$32,	%%rdx	\n\t"                                                         \
92                              "movq	%%rdx,	%1	\n\t"                                                          \
93                              : "=m"(*((unsigned long *)(gate_selector_addr))),                              \
94                                "=m"(*(1 + (unsigned long *)(gate_selector_addr))), "=&a"(__d0), "=&d"(__d1) \
95                              : "i"(attr << 8),                                                              \
96                                "3"((unsigned long *)(code_addr)), "2"(0x8 << 16), "c"(ist)                  \
97                              : "memory");                                                                   \
98     } while (0)
99 
set_tss_descriptor(unsigned int n,void * addr)100 void set_tss_descriptor(unsigned int n, void *addr)
101 {
102 
103     unsigned long limit = 103;
104 
105     *(unsigned long *)(phys_2_virt(GDT_Table + n)) = (limit & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | ((((unsigned long)addr >> 16) & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((limit >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute
106     *(unsigned long *)(phys_2_virt(GDT_Table + n + 1)) = (((unsigned long)addr >> 32) & 0xffffffff) | 0;
107 }
108 
109 /**
110  * @brief 加载任务状态段寄存器
111  * @param n TSS基地址在GDT中的第几项
112  * 左移3位的原因是GDT每项占8字节
113  */
114 #define load_TR(n)                                        \
115     do                                                    \
116     {                                                     \
117         __asm__ __volatile__("ltr %%ax" ::"a"((n) << 3)); \
118     } while (0)
119 
120 /**
121  * @brief 设置中断门
122  *
123  * @param n 中断号
124  * @param ist ist
125  * @param addr 服务程序的地址
126  */
set_intr_gate(unsigned int n,unsigned char ist,void * addr)127 void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
128 {
129     _set_gate(phys_2_virt(IDT_Table + n), 0x8E, ist, addr); // p=1,DPL=0, type=E
130 
131     //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1,DPL=0, type=E
132 }
133 
134 /**
135  * @brief 设置64位,DPL=0的陷阱门
136  *
137  * @param n 中断号
138  * @param ist ist
139  * @param addr 服务程序的地址
140  */
set_trap_gate(unsigned int n,unsigned char ist,void * addr)141 void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
142 {
143     // kdebug("addr=%#018lx", (ul)(addr));
144 
145     //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1,DPL=0, type=F
146     _set_gate(phys_2_virt(IDT_Table + n), 0x8F, ist, addr); // p=1,DPL=0, type=F
147 }
148 
149 /**
150  * @brief 设置64位,DPL=3的陷阱门
151  *
152  * @param n 中断号
153  * @param ist ist
154  * @param addr 服务程序的地址
155  */
set_system_trap_gate(unsigned int n,unsigned char ist,void * addr)156 void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr)
157 {
158     // kdebug("addr=%#018lx", (ul)(addr));
159 
160     //set_gate((ul *)phys_2_virt(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1,DPL=3, type=F
161     _set_gate(phys_2_virt(IDT_Table + n), 0xEF, ist, addr); // p=1,DPL=3, type=F
162 }
163 
164 
set_system_intr_gate(unsigned int n,unsigned char ist,void * addr)165 static inline void set_system_intr_gate(unsigned int n,unsigned char ist,void * addr)	//int3
166 {
167 	_set_gate(phys_2_virt(IDT_Table + n) , 0xEE , ist , addr);	//P,DPL=3,TYPE=E
168 }
169 /**
170  * @brief 初始化TSS表的内容
171  *
172  */
173 
set_tss64(unsigned int * Table,unsigned long rsp0,unsigned long rsp1,unsigned long rsp2,unsigned long ist1,unsigned long ist2,unsigned long ist3,unsigned long ist4,unsigned long ist5,unsigned long ist6,unsigned long ist7)174 void set_tss64(unsigned int *Table, unsigned long rsp0, unsigned long rsp1, unsigned long rsp2, unsigned long ist1, unsigned long ist2, unsigned long ist3,
175                unsigned long ist4, unsigned long ist5, unsigned long ist6, unsigned long ist7)
176 {
177     *(unsigned long *)(Table + 1) = rsp0;
178     *(unsigned long *)(Table + 3) = rsp1;
179     *(unsigned long *)(Table + 5) = rsp2;
180 
181     *(unsigned long *)(Table + 9) = ist1;
182     *(unsigned long *)(Table + 11) = ist2;
183     *(unsigned long *)(Table + 13) = ist3;
184     *(unsigned long *)(Table + 15) = ist4;
185     *(unsigned long *)(Table + 17) = ist5;
186     *(unsigned long *)(Table + 19) = ist6;
187     *(unsigned long *)(Table + 21) = ist7;
188 }
189 #endif
190 
191 #pragma GCC pop_options