nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
segment.c
Go to the documentation of this file.
1 #include <slibc.h>
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <stddef.h>
5 #include <string.h>
6 
7 #include <segment.h>
8 
9 #define GDT_SET(entry, t, d, b, l) \
10 do { \
11  unsigned long limit; \
12  (entry).type = (t); \
13  (entry).dpl = (d); \
14  (entry).s = 1; \
15  (entry).p = 1; \
16  (entry).avl = 0; \
17  (entry).zero = 0; \
18  (entry).size = 1; \
19  (entry).g = 1; \
20  (entry).base0 = (b) & 0x0000FFFFu; \
21  (entry).base1 = ((b) & 0x00FF0000u) >> 16; \
22  (entry).base2 = ((b) >> 24) & 0x0FFu; \
23  limit = (entry).g ? ((l) >> 12) : ((l) & 0x000FFFFF); \
24  (entry).limit0 = limit & 0x0000FFFFu; \
25  (entry).limit1 = (limit >> 16) & 0x0000000Fu; \
26 } while (0)
27 
28 #define TSS_SET(entry, d, b, l) \
29 do { \
30  unsigned long limit; \
31  (entry).type = 0x09; \
32  (entry).dpl = (d); \
33  (entry).p = 1; \
34  (entry).avl = 0; \
35  (entry).zero1 = 0; \
36  (entry).zero2 = 0; \
37  (entry).g = 0; \
38  (entry).base_low = (b) & 0x0000FFFF; \
39  (entry).base_high_low = ((b) & 0x00FF0000) >> 16; \
40  (entry).base_high_high= ((b) >> 24) & 0x000000FF; \
41  limit = (entry).g ? ((l) >> 12) : ((l) & 0x000FFFFF); \
42  (entry).segment_limit_low = limit & 0x0000FFFFu; \
43  (entry).segment_limit_high = (limit >> 16) & 0x0000000Fu; \
44 } while (0)
45 
46 static struct segment s_gdt[DESC_COUNT];
47 static struct tss32 s_tss = {
48  .io_map_base_address = (sizeof(s_tss) - IO_BITMAP_SIZE),
49  .io_bitmap = { '\0', },
50 };
51 
52 void segment_init(void)
53 {
54  struct gdtr gdtr;
55  struct tss *tss;
56 
57  memset(s_gdt + 0, 0, sizeof(*s_gdt));
58  GDT_SET(s_gdt[DESC_KERNEL_CS],
59  CODE | READABLE, KERNEL, 0x0, 0xFFFFFFFF);
60  GDT_SET(s_gdt[DESC_KERNEL_DS], WRITABLE, KERNEL, 0x0, 0xFFFFFFFF);
61  GDT_SET(s_gdt[DESC_KERNEL_SS], WRITABLE, KERNEL, 0x0, 0xFFFFFFFF);
62 
63  GDT_SET(s_gdt[DESC_USER_CS], CODE | READABLE, USER, 0x0, 0xFFFFFFFF);
64  GDT_SET(s_gdt[DESC_USER_DS], WRITABLE, USER, 0x0, 0xFFFFFFFF);
65  GDT_SET(s_gdt[DESC_USER_SS], WRITABLE, USER, 0x0, 0xFFFFFFFF);
66 
67  tss = (struct tss*)(s_gdt + DESC_TSS);
68  TSS_SET(*tss, KERNEL, (unsigned long)&s_tss, sizeof(s_tss));
69 
70  gdtr.base = (unsigned long)s_gdt;
71  gdtr.limit = sizeof(s_gdt) - 1;
72 
73  asm volatile ("lgdt (%0)"::"g"(&gdtr));
74  asm volatile (
75  "ltr %0"
76  :
77  :"a"((unsigned short)(DESC_TSS << SIZEOF_A_DESC_BIT))
78  );
79 }
80 
81 unsigned char *tss_io_bitmap_get(void)
82 {
83  return (unsigned char *)s_tss.io_bitmap;
84 }
85 
86 void tss_update_kernel_stack(unsigned long esp)
87 {
88  s_tss.ss0 = (DESC_KERNEL_SS << 3) | TI(GDT) | KERNEL;
89  s_tss.esp0 = esp;
90 }
91 
92 /* End of a file */