blob: c91524a4353c4821e25810ac9ba3d7e76e26c745 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
// http://wiki.osdev.org/GDT_Tutorial
#include "kernel/kernel.h"
#include "kernel/gdt.h"
#include <stdint.h>
#define GDT_SIZE 6
//https://wiki.osdev.org/Task_State_Segment
tss_struct sys_tss[SMP_MAX_PROC]; //Define the TSS as a global structure
void install_tss(uint32_t esp0){
// now fill each value
// set values necessary
sys_tss[0].ss0 = 0x10; //kernel data
sys_tss[0].esp0 = esp0;
// now set the IO bitmap (not necessary, so set above limit)
// sys_tss.iomap = ( unsigned short ) sizeof( tss_struct );
}
typedef struct GDT_struct
{
uint32_t base;
uint32_t limit;
uint32_t type;
}GDT;
//alternative
struct gdt_entry_bits
{
unsigned int limit_low:16;
unsigned int base_low : 24;
//attribute byte split into bitfields
unsigned int accessed :1;
unsigned int read_write :1; //readable for code, writable for data
unsigned int conforming_expand_down :1; //conforming for code, expand down for data
unsigned int code :1; //1 for code, 0 for data
unsigned int always_1 :1; //should be 1 for everything but TSS and LDT
unsigned int DPL :2; //priveledge level
unsigned int present :1;
//and now into granularity
unsigned int limit_high :4;
unsigned int available :1;
unsigned int always_0 :1; //should always be 0
unsigned int big :1; //32bit opcodes for code, uint32_t stack for data
unsigned int gran :1; //1 to use 4k page addressing, 0 for byte addressing
unsigned int base_high :8;
} __packed; //or __attribute__((packed))
/**
* \param target A pointer to the 8-byte GDT entry
* \param source An arbitrary structure describing the GDT entry
*/
void encodeGdtEntry(uint8_t *target, GDT source)
{
// Check the limit to make sure that it can be encoded
if ((source.limit > 65536) && (source.limit & 0xFFF) != 0xFFF)
{
kpanic("trying to set an invalid GDT source.limit!");
}
if (source.limit > 65536) {
// Adjust granularity if required
source.limit = source.limit >> 12;
target[6] = 0xC0;
} else {
target[6] = 0x40;
}
// Encode the limit
target[0] = source.limit & 0xFF;
target[1] = (source.limit >> 8) & 0xFF;
// Encode the base
target[2] = source.base & 0xFF;
target[3] = (source.base >> 8) & 0xFF;
target[4] = (source.base >> 16) & 0xFF;
target[7] = (source.base >> 24) & 0xFF;
target[5] = source.type;
target[6] |= (source.limit >> 16) & 0xF;
// And... Type
/*
0 1 dw 0xffff ;limit
2 3 dw 0x0 ;base
4 db 0x0 ;base
5 db 10011010b ;flags
6 db 11001111b ;flags & seg.limit
7 db 0x0 ;base
*/
}
void gdt_init()
{
static int last_cpu=0;
/*
Pr=1 Privl 1 Exec DC RW Ac
0x9A == 1001 1010 == 1 00 1 1 0 1 0
0x92 == 1001 0010 == 1 00 1 0 0 1 0
0xFA == 1111 1010 == 1 11 1 1 0 1 0
0xF2 == 1111 0010 == 1 11 1 0 0 1 0
*/
//static uint8_t gdt_struct[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE
uint8_t *gdt_struct=kballoc(1); //[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE
GDT myGDT[GDT_SIZE];
//selector 0x0
myGDT[0].base=0;
myGDT[0].limit=0;
myGDT[0].type=0;
//selector 0x8 code
myGDT[1].base=0;
myGDT[1].limit=0xffffffff;
myGDT[1].type=0x9a;
//selector 0x10 data
myGDT[2].base=0;
myGDT[2].limit=0xffffffff;
myGDT[2].type=0x92;
//selector 0x18 code user
myGDT[3].base=0;
myGDT[3].limit=0xffffffff;
myGDT[3].type=0xFa;
//selector 0x20 data user
myGDT[4].base=0;
myGDT[4].limit=0xffffffff;
myGDT[4].type=0xF2;
//TSS 0x28
myGDT[5].base=&sys_tss[last_cpu++]; //tss start
myGDT[5].limit=sizeof(tss_struct); //tss end
myGDT[5].type=0x89;
// transcript to format the processor wants
for(int i=0;i<GDT_SIZE;i++)
encodeGdtEntry(&gdt_struct[8*i],myGDT[i]);
// update tss entry
install_tss(0);
setup_gdt(gdt_struct);
}
void setup_gdt(uint8_t *gdt_struct)
{
asm_setup_gdt(&gdt_struct[0],8*GDT_SIZE);
}
|