blob: 4bc7ca27c78c1953ac7155749aa6136a733caf8e (
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
|
// http://wiki.osdev.org/GDT_Tutorial
#include "lib/logger/log.h"
#include "usermode.h"
#define FOOLOS_MODULE_NAME "GDT"
#include <stdint.h>
#define GDT_SIZE 6
extern sys_tss;
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))
static GDT myGDT[GDT_SIZE];
static uint8_t gdt_struct[GDT_SIZE*8];
/**
* \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)
{
panic(FOOLOS_MODULE_NAME,"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_setup()
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"setting up Global Descriptor Table");
//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; //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]);
// updat
install_tss();
setup_gdt(&gdt_struct[0],8*GDT_SIZE);
}
|