rev |
line source |
nuclear@7
|
1 #include <string.h>
|
nuclear@7
|
2 #include "segm.h"
|
nuclear@10
|
3 #include "desc.h"
|
nuclear@55
|
4 #include "tss.h"
|
nuclear@7
|
5
|
nuclear@8
|
6 /* bits for the 3rd 16bt part of the descriptor */
|
nuclear@7
|
7 #define BIT_ACCESSED (1 << 8)
|
nuclear@7
|
8 #define BIT_WR (1 << 9)
|
nuclear@7
|
9 #define BIT_RD (1 << 9)
|
nuclear@7
|
10 #define BIT_EXP_DOWN (1 << 10)
|
nuclear@7
|
11 #define BIT_CONFORMING (1 << 10)
|
nuclear@7
|
12 #define BIT_CODE (1 << 11)
|
nuclear@7
|
13 #define BIT_NOSYS (1 << 12)
|
nuclear@7
|
14 #define BIT_PRESENT (1 << 15)
|
nuclear@29
|
15 /* TSS busy bit */
|
nuclear@29
|
16 #define BIT_BUSY (1 << 9)
|
nuclear@7
|
17
|
nuclear@8
|
18 /* bits for the last 16bit part of the descriptor */
|
nuclear@7
|
19 #define BIT_BIG (1 << 6)
|
nuclear@7
|
20 #define BIT_DEFAULT (1 << 6)
|
nuclear@7
|
21 #define BIT_GRAN (1 << 7)
|
nuclear@7
|
22
|
nuclear@7
|
23 enum {TYPE_DATA, TYPE_CODE};
|
nuclear@7
|
24
|
nuclear@55
|
25 /* we need the following bit pattern at the 8th bit excluding the busy bit: 1001 */
|
nuclear@55
|
26 #define TSS_TYPE_BITS (9 << 8)
|
nuclear@29
|
27
|
nuclear@7
|
28 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type);
|
nuclear@55
|
29 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl);
|
nuclear@7
|
30
|
nuclear@8
|
31 /* these functions are implemented in segm-asm.S */
|
nuclear@8
|
32 void setup_selectors(uint16_t code, uint16_t data);
|
nuclear@8
|
33 void set_gdt(uint32_t addr, uint16_t limit);
|
nuclear@54
|
34 void set_task_reg(uint16_t tss_selector);
|
nuclear@7
|
35
|
nuclear@8
|
36
|
nuclear@8
|
37 /* our global descriptor table */
|
nuclear@29
|
38 static desc_t gdt[6];
|
nuclear@7
|
39
|
nuclear@7
|
40
|
nuclear@7
|
41 void init_segm(void)
|
nuclear@7
|
42 {
|
nuclear@7
|
43 memset(gdt, 0, sizeof gdt);
|
nuclear@7
|
44 segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE);
|
nuclear@7
|
45 segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA);
|
nuclear@29
|
46 segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE);
|
nuclear@29
|
47 segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA);
|
nuclear@7
|
48
|
nuclear@7
|
49 set_gdt((uint32_t)gdt, sizeof gdt - 1);
|
nuclear@7
|
50
|
nuclear@7
|
51 setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0));
|
nuclear@7
|
52 }
|
nuclear@7
|
53
|
nuclear@8
|
54 /* constructs a GDT selector based on index and priviledge level */
|
nuclear@7
|
55 uint16_t selector(int idx, int rpl)
|
nuclear@7
|
56 {
|
nuclear@7
|
57 return (idx << 3) | (rpl & 3);
|
nuclear@7
|
58 }
|
nuclear@7
|
59
|
nuclear@54
|
60 void set_tss(uint32_t addr)
|
nuclear@54
|
61 {
|
nuclear@55
|
62 task_desc(gdt + SEGM_TASK, addr, sizeof(struct task_state) - 1, 3);
|
nuclear@54
|
63 set_task_reg(selector(SEGM_TASK, 0));
|
nuclear@54
|
64 }
|
nuclear@54
|
65
|
nuclear@7
|
66 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type)
|
nuclear@7
|
67 {
|
nuclear@7
|
68 desc->d[0] = limit & 0xffff; /* low order 16bits of limit */
|
nuclear@7
|
69 desc->d[1] = base & 0xffff; /* low order 16bits of base */
|
nuclear@7
|
70
|
nuclear@7
|
71 /* third 16bit part contains the last 8 bits of base, the 2 priviledge
|
nuclear@7
|
72 * level bits starting on bit 13, present flag on bit 15, and type bits
|
nuclear@7
|
73 * starting from bit 8
|
nuclear@7
|
74 */
|
nuclear@7
|
75 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
|
nuclear@7
|
76 BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE));
|
nuclear@7
|
77
|
nuclear@7
|
78 /* last 16bit part contains the last nibble of limit, the last byte of
|
nuclear@7
|
79 * base, and the granularity and deafult/big flags in bits 23 and 22 resp.
|
nuclear@7
|
80 */
|
nuclear@7
|
81 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG;
|
nuclear@7
|
82 }
|
nuclear@29
|
83
|
nuclear@55
|
84 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl)
|
nuclear@29
|
85 {
|
nuclear@29
|
86 desc->d[0] = limit & 0xffff;
|
nuclear@29
|
87 desc->d[1] = base & 0xffff;
|
nuclear@29
|
88
|
nuclear@29
|
89 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
|
nuclear@55
|
90 TSS_TYPE_BITS; /* XXX busy ? */
|
nuclear@29
|
91 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN;
|
nuclear@29
|
92 }
|
nuclear@55
|
93 /*
|
nuclear@55
|
94 static void dbg_print_gdt(void)
|
nuclear@55
|
95 {
|
nuclear@55
|
96 int i;
|
nuclear@55
|
97
|
nuclear@55
|
98 printf("Global Descriptor Table\n");
|
nuclear@55
|
99 printf("-----------------------\n");
|
nuclear@55
|
100
|
nuclear@55
|
101 for(i=0; i<6; i++) {
|
nuclear@55
|
102 print_desc(gdt + i);
|
nuclear@55
|
103 }
|
nuclear@55
|
104 }
|
nuclear@55
|
105
|
nuclear@55
|
106 static void print_desc(desc_t *desc)
|
nuclear@55
|
107 {
|
nuclear@55
|
108 uint32_t base, limit;
|
nuclear@55
|
109 int dpl, g, db, l, avl, p, s, type;
|
nuclear@55
|
110 char *type_str;
|
nuclear@55
|
111
|
nuclear@55
|
112 base = (uint32_t)desc->d[1] | ((uint32_t)(desc->d[2] & 0xff) << 16) | ((uint32_t)(desc->d[3] >> 8) << 24);
|
nuclear@55
|
113 limit = (uint32_t)desc->d[0] | ((uint32_t)(desc->d[3] & 0xf) << 16);
|
nuclear@55
|
114 dpl = (desc->d[2] >> 13) & 3;
|
nuclear@55
|
115 type = (desc->d[2] >> 8) & 0xf;
|
nuclear@55
|
116 g = (desc->d[3] >> 23) & 1;
|
nuclear@55
|
117 db = (desc->d[3] >> 22) & 1;
|
nuclear@55
|
118 l = (desc->d[3] >> 21) & 1;
|
nuclear@55
|
119 avl = (desc->d[3] >> 20) & 1;
|
nuclear@55
|
120
|
nuclear@55
|
121 p = (desc->d[2] >> 15) & 1;
|
nuclear@55
|
122 s = (desc->d[2] >> 12) & 1;
|
nuclear@55
|
123 }
|
nuclear@55
|
124 */
|