blob: 46bf61a44a41d7c06e4cbf7b2d38e242f3f0b538 (
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
|
// http://wiki.osdev.org/GDT_Tutorial
#include "usermode.h"
#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_init()
{
//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);
}
|