Skip to content

Commit 96eafea

Browse files
committed
Merge branch 'khorben/tss'
2 parents f94ea31 + abf21de commit 96eafea

File tree

5 files changed

+177
-34
lines changed

5 files changed

+177
-34
lines changed

src/arch/i386/gdt.h

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,65 @@ typedef struct _GDTTable
2323
unsigned int prot;
2424
} GDTTable;
2525

26+
#pragma pack(1)
27+
typedef struct _TSS
28+
{
29+
uint16_t link;
30+
uint16_t __padding0;
31+
uint32_t esp0;
32+
uint16_t ss0;
33+
uint16_t __padding1;
34+
uint32_t esp1;
35+
uint16_t ss1;
36+
uint16_t __padding2;
37+
uint32_t esp2;
38+
uint16_t ss2;
39+
uint16_t __padding3;
40+
uint32_t cr3;
41+
uint32_t eip;
42+
uint32_t eflags;
43+
uint32_t eax;
44+
uint32_t ecx;
45+
uint32_t edx;
46+
uint32_t ebx;
47+
uint32_t esp;
48+
uint32_t ebp;
49+
uint32_t esi;
50+
uint32_t edi;
51+
uint16_t es;
52+
uint16_t __padding4;
53+
uint16_t cs;
54+
uint16_t __padding5;
55+
uint16_t ss;
56+
uint16_t __padding6;
57+
uint16_t ds;
58+
uint16_t __padding7;
59+
uint16_t fs;
60+
uint16_t __padding8;
61+
uint16_t gs;
62+
uint16_t __padding9;
63+
uint16_t ldtr;
64+
uint16_t __padding10;
65+
uint16_t __padding11;
66+
uint16_t iopb;
67+
uint32_t ssp;
68+
} TSS;
69+
#pragma pack()
70+
71+
72+
/* constants */
73+
# define GDT_SYSTEM_TYPE_LDT 0x2
74+
# define GDT_SYSTEM_TYPE_TSS 0x9
75+
2676

2777
/* prototypes */
2878
GDT * gdt_init(void);
29-
int gdt_init_table(GDTTable const * table, size_t count);
79+
int gdt_init_table(GDTTable const * table, size_t table_cnt, size_t tss_cnt);
3080

3181

3282
/* useful */
3383
int gdt_append(GDT * gdt, vaddr_t base, size_t size, unsigned int prot);
84+
int gdt_append_system(GDT * gdt, void * base, size_t size, unsigned int type);
3485

3586
void gdt_apply(GDT * gdt);
3687

src/kernel/multiboot.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* $Id$ */
2-
/* Copyright (c) 2018-2019 Pierre Pronchery <[email protected]> */
2+
/* Copyright (c) 2018-2025 Pierre Pronchery <[email protected]> */
33
/* This file is part of DeforaOS uKernel */
44

55

@@ -92,7 +92,7 @@ int multiboot(const ukMultibootInfo * mi)
9292
if(_arch_setgdt64(_gdt_4gb, sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
9393
#else
9494
if(gdt_init_table((const GDTTable *)&_gdt_4gb,
95-
sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
95+
sizeof(_gdt_4gb) / sizeof(*_gdt_4gb), 1) != 0)
9696
#endif
9797
{
9898
puts("Could not setup the GDT");

src/loader/gdt.c

Lines changed: 114 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
/* access */
2121
# define GDT_ACCESS_SET 0x01
22-
# define GDT_ACCESS_RW 0x02
23-
# define GDT_ACCESS_X 0x08
22+
# define GDT_ACCESS_PROT_RW 0x02
23+
# define GDT_ACCESS_PROT_X 0x08
2424
# define GDT_ACCESS_SEGMENT 0x10
2525
# define GDT_ACCESS_RING(level) ((level) << 5)
2626
# define GDT_ACCESS_PRESENT 0x80
@@ -48,6 +48,21 @@ typedef struct _GDTEntry
4848
} GDTEntry;
4949
#pragma pack()
5050

51+
#pragma pack(1)
52+
typedef struct _LDT
53+
{
54+
uint8_t limit0;
55+
uint8_t limit1;
56+
uint8_t base0;
57+
uint8_t base1;
58+
uint8_t base2;
59+
uint8_t access;
60+
unsigned int limit2:4;
61+
unsigned int flags:4;
62+
uint8_t base3;
63+
} LDT;
64+
#pragma pack()
65+
5166
struct _GDT
5267
{
5368
GDTEntry entries[GDT_ENTRIES_MAX];
@@ -58,9 +73,13 @@ struct _GDT
5873
/* prototypes */
5974
extern void __arch_setgdt(GDTEntry const * entries, size_t count);
6075

76+
static int _gdt_append_entry(GDT * gdt, vaddr_t base, uint32_t limit,
77+
uint8_t access, uint8_t flags);
78+
6179

6280
/* variables */
6381
static GDT _gdt;
82+
static TSS _tss;
6483

6584

6685
/* functions */
@@ -74,17 +93,27 @@ GDT * gdt_init(void)
7493

7594

7695
/* gdt_init_table */
77-
int gdt_init_table(GDTTable const * table, size_t count)
96+
int gdt_init_table(GDTTable const * table, size_t table_cnt, size_t tss_cnt)
7897
{
7998
int ret = 0;
8099
GDT * gdt;
81100
size_t i;
82101

83102
gdt = gdt_init();
84-
for(i = 0; i < count; i++)
103+
for(i = 0; i < table_cnt; i++)
85104
if((ret = gdt_append(gdt, table[i].base, table[i].size,
86105
table[i].prot)) != 0)
87106
return ret;
107+
/* set the TSS */
108+
if(tss_cnt > 1)
109+
{
110+
errno = ENOSYS;
111+
return -1;
112+
}
113+
else if(tss_cnt == 1 && (ret = gdt_append_system(gdt, &_tss,
114+
sizeof(_tss), GDT_SYSTEM_TYPE_TSS))
115+
!= 0)
116+
return ret;
88117
gdt_apply(gdt);
89118
return 0;
90119
}
@@ -94,10 +123,9 @@ int gdt_init_table(GDTTable const * table, size_t count)
94123
/* gdt_append */
95124
int gdt_append(GDT * gdt, vaddr_t base, size_t size, unsigned int prot)
96125
{
97-
GDTEntry * entry;
98126
uint32_t limit;
99-
uint8_t access = GDT_ACCESS_PRESENT
100-
| GDT_ACCESS_SEGMENT | GDT_ACCESS_RING(0);
127+
uint8_t access = GDT_ACCESS_SEGMENT | GDT_ACCESS_PRESENT
128+
| GDT_ACCESS_RING(0);
101129
uint8_t flags = GDT_FLAG_PROTECTED_MODE;
102130

103131
/* check for errors */
@@ -106,9 +134,7 @@ int gdt_append(GDT * gdt, vaddr_t base, size_t size, unsigned int prot)
106134
errno = ERANGE;
107135
return -1;
108136
}
109-
if(gdt->entries_cnt >= sizeof(gdt->entries) / sizeof(*gdt->entries)
110-
|| size > ULONG_MAX
111-
|| ULONG_MAX - size < base)
137+
if(size > ULONG_MAX || ULONG_MAX - size < base)
112138
{
113139
errno = ENOMEM;
114140
return -1;
@@ -120,41 +146,72 @@ int gdt_append(GDT * gdt, vaddr_t base, size_t size, unsigned int prot)
120146
errno = EPERM;
121147
return -1;
122148
}
123-
entry = &gdt->entries[gdt->entries_cnt];
124-
/* base */
125-
entry->base0 = base & 0xff;
126-
entry->base1 = (base & 0xff00) >> 8;
127-
entry->base2 = (base & 0xff0000) >> 16;
128-
entry->base3 = (base & 0xff000000) >> 24;
129149
/* limit */
130150
if(size - 1 > GDT_LIMIT_MAX)
131151
{
132152
limit = (size & 0xfff) == 0
133-
? (size >> 12)
134-
: (((size | 0xfff) + 1) >> 12);
135-
limit--;
153+
? (size >> 12) - 1
154+
: (((size | 0xfff) + 1) >> 12) - 1;
136155
flags |= GDT_FLAG_PAGE_GRANULARITY;
137156
}
138157
else
139158
limit = size - 1;
140-
entry->limit0 = limit & 0xff;
141-
entry->limit1 = (limit & 0xff00) >> 8;
142-
entry->limit2 = (limit & 0xf0000) >> 16;
143159
/* access */
144160
if(prot == (PROT_READ | PROT_EXEC))
145161
/* code segment */
146-
access |= GDT_ACCESS_RW | GDT_ACCESS_X;
162+
access |= GDT_ACCESS_PROT_RW | GDT_ACCESS_PROT_X;
147163
else if(prot == (PROT_READ | PROT_WRITE))
148164
/* data segment (read/write) */
149-
access |= GDT_ACCESS_RW;
165+
access |= GDT_ACCESS_PROT_RW;
150166
else if(prot == PROT_READ)
151167
/* data segment (read-only) */
152168
access |= GDT_ACCESS_SET;
153-
entry->access = access;
154-
/* flags */
155-
entry->flags = flags;
156-
gdt->entries_cnt++;
157-
return 0;
169+
return _gdt_append_entry(gdt, base, limit, access, flags);
170+
}
171+
172+
173+
/* gdt_append_system */
174+
static int _append_system_ldt(GDT * gdt, void * base, size_t size);
175+
static int _append_system_tss(GDT * gdt, void * base, size_t size);
176+
177+
int gdt_append_system(GDT * gdt, void * base, size_t size, unsigned int type)
178+
{
179+
switch(type)
180+
{
181+
case GDT_SYSTEM_TYPE_LDT:
182+
return _append_system_ldt(gdt, base, size);
183+
case GDT_SYSTEM_TYPE_TSS:
184+
return _append_system_tss(gdt, base, size);
185+
default:
186+
errno = ENOSYS;
187+
return -1;
188+
}
189+
}
190+
191+
static int _append_system_ldt(GDT * gdt, void * base, size_t size)
192+
{
193+
uint32_t access = GDT_ACCESS_PRESENT | GDT_SYSTEM_TYPE_LDT;
194+
uint8_t flags = GDT_FLAG_PROTECTED_MODE;
195+
196+
if(size != sizeof(LDT))
197+
{
198+
errno = ERANGE;
199+
return -1;
200+
}
201+
return _gdt_append_entry(gdt, (vaddr_t)base, size - 1, access, flags);
202+
}
203+
204+
static int _append_system_tss(GDT * gdt, void * base, size_t size)
205+
{
206+
uint32_t access = GDT_ACCESS_PRESENT | GDT_SYSTEM_TYPE_TSS;
207+
uint8_t flags = GDT_FLAG_PROTECTED_MODE;
208+
209+
if(size != sizeof(TSS))
210+
{
211+
errno = ERANGE;
212+
return -1;
213+
}
214+
return _gdt_append_entry(gdt, (vaddr_t)base, size - 1, access, flags);
158215
}
159216

160217

@@ -163,4 +220,32 @@ void gdt_apply(GDT * gdt)
163220
{
164221
__arch_setgdt(gdt->entries, gdt->entries_cnt);
165222
}
223+
224+
225+
/* private */
226+
/* gdt_append_entry */
227+
static int _gdt_append_entry(GDT * gdt, vaddr_t base, uint32_t limit,
228+
uint8_t access, uint8_t flags)
229+
{
230+
GDTEntry * entry;
231+
232+
/* check for errors */
233+
if(gdt->entries_cnt >= sizeof(gdt->entries) / sizeof(*gdt->entries))
234+
{
235+
errno = ENOMEM;
236+
return -1;
237+
}
238+
entry = &gdt->entries[gdt->entries_cnt];
239+
entry->base0 = base & 0xff;
240+
entry->base1 = (base & 0xff00) >> 8;
241+
entry->base2 = (base & 0xff0000) >> 16;
242+
entry->base3 = (base & 0xff000000) >> 24;
243+
entry->limit0 = limit & 0xff;
244+
entry->limit1 = (limit & 0xff00) >> 8;
245+
entry->limit2 = (limit & 0xf0000) >> 16;
246+
entry->access = access;
247+
entry->flags = flags;
248+
gdt->entries_cnt++;
249+
return 0;
250+
}
166251
#endif

src/loader/multiboot.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* $Id$ */
2-
/* Copyright (c) 2018-2020 Pierre Pronchery <[email protected]> */
2+
/* Copyright (c) 2018-2025 Pierre Pronchery <[email protected]> */
33
/* This file is part of DeforaOS uKernel */
44

55

@@ -87,7 +87,7 @@ int multiboot(const ukMultibootInfo * mi)
8787

8888
/* setup the GDT */
8989
if(gdt_init_table((const GDTTable *)&_gdt_4gb,
90-
sizeof(_gdt_4gb) / sizeof(*_gdt_4gb)) != 0)
90+
sizeof(_gdt_4gb) / sizeof(*_gdt_4gb), 1) != 0)
9191
{
9292
puts("Could not setup the GDT");
9393
return 4;

tests/gdt.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313

1414
#if defined(__amd64__) || defined(__i386__)
15+
/* variables */
16+
static TSS tss;
17+
18+
19+
/* functions */
1520
/* __arch_setgdt */
1621
void __arch_setgdt(GDTEntry const * entries, size_t count)
1722
{
@@ -51,6 +56,7 @@ int main(int argc, char * argv[])
5156
gdt = gdt_init();
5257
gdt_append(gdt, 0x00000000, 0xffffffff, PROT_READ | PROT_EXEC);
5358
gdt_append(gdt, 0x00000000, 0xffffffff, PROT_READ | PROT_WRITE);
59+
gdt_append_system(gdt, &tss, sizeof(tss), GDT_SYSTEM_TYPE_TSS);
5460
gdt_apply(gdt);
5561

5662
/* 4 MB code + 4 MB data (read-write) + 4 MB data (read-only) */
@@ -59,6 +65,7 @@ int main(int argc, char * argv[])
5965
gdt_append(gdt, 0x00400000, 0x00400000, PROT_READ | PROT_EXEC);
6066
gdt_append(gdt, 0x00800000, 0x00400000, PROT_READ | PROT_WRITE);
6167
gdt_append(gdt, 0x00c00000, 0x00400000, PROT_READ);
68+
gdt_append_system(gdt, &tss, sizeof(tss), GDT_SYSTEM_TYPE_TSS);
6269
gdt_apply(gdt);
6370

6471
#endif

0 commit comments

Comments
 (0)