UnnamedOS
gdt.c
Go to the documentation of this file.
1 
19 #include <common.h>
20 #include <mem/gdt.h>
21 #include <tasks/tss.h>
22 
24 typedef struct {
25  uint16_t limit;
26  uint32_t base;
27 } __attribute__((packed)) gdtr_t;
28 
31 typedef union {
32  struct {
33  uint16_t dpl : 2,
34  idt : 1,
35  entry : 13;
36  } __attribute__((packed)) bits;
37  uint16_t word;
39 
42 
49 void gdt_init_entry(size_t entry, uint32_t base, uint32_t limit) {
50  gdt[entry].base0_23 = base & 0xFFFFFF; // 24 lower bits
51  gdt[entry].base24_31 = (base >> 24) & 0xFF; // 8 higher bits
52  gdt[entry].limit0_15 = limit & 0xFFFF; // 16 lower bits
53  gdt[entry].limit16_19 = (limit >> 16) & 0xF; // 4 higher bits
54  gdt[entry].reserved = 0;
55 }
56 
58 static void gdt_load() {
59  gdtr_t gdtr = {.base = (uint32_t) gdt, .limit = sizeof(gdt) - 1};
60  asm volatile("lgdt %0" : : "m" (gdtr));
61 }
62 
67 extern void gdt_flush();
68 
72 void gdt_init() {
73  print("GDT init ... ");
74  gdt_init_entry(0, 0, 0);
75  gdt_init_entry(GDT_RING0_CODE_SEG, 0, 0xFFFFF);
76  gdt_init_entry(GDT_RING0_DATA_SEG, 0, 0xFFFFF);
77  gdt_init_entry(GDT_RING3_CODE_SEG, 0, 0xFFFFF);
78  gdt_init_entry(GDT_RING3_DATA_SEG, 0, 0xFFFFF);
79  gdt[0].ac = 0; gdt[0].rw = 0; gdt[0].dc = 0; gdt[0].ex = 0; gdt[0].dt = 0; gdt[0].dpl = 0; gdt[0].pr = 0; gdt[0].sz = 0; gdt[0].gr = 0;
80  gdt[1].ac = 0; gdt[1].rw = 1; gdt[1].dc = 0; gdt[1].ex = 1; gdt[1].dt = 1; gdt[1].dpl = 0; gdt[1].pr = 1; gdt[1].sz = 1; gdt[1].gr = 1;
81  gdt[2].ac = 0; gdt[2].rw = 1; gdt[2].dc = 0; gdt[2].ex = 0; gdt[2].dt = 1; gdt[2].dpl = 0; gdt[2].pr = 1; gdt[2].sz = 1; gdt[2].gr = 1;
82  gdt[3].ac = 0; gdt[3].rw = 1; gdt[3].dc = 0; gdt[3].ex = 1; gdt[3].dt = 1; gdt[3].dpl = 3; gdt[3].pr = 1; gdt[3].sz = 1; gdt[3].gr = 1;
83  gdt[4].ac = 0; gdt[4].rw = 1; gdt[4].dc = 0; gdt[4].ex = 0; gdt[4].dt = 1; gdt[4].dpl = 3; gdt[4].pr = 1; gdt[4].sz = 1; gdt[4].gr = 1;
84  tss_init(gdt);
85  gdt_load();
87  gdt_flush();
88  tss_load();
89  println("%2aok%a.");
90 }
91 
103 uint16_t gdt_get_selector(size_t entry) {
104  gdt_selector_t selector = {.bits = {.dpl = gdt[entry].dpl, .entry = entry}};
105  return (uint16_t) selector.word; // selector used in IDT and segment registers
106 }
107 
#define GDT_RING3_DATA_SEG
user data segment index
Definition: gdt.h:16
uint8_t dpl
Descriptor privilege level.
Definition: gdt.h:28
uint8_t dc
direction / conforming
Definition: gdt.h:25
uint8_t ac
accessed
Definition: gdt.h:23
the GDTR register pointing to the GDT
Definition: gdt.c:24
uint8_t dt
descriptor type
Definition: gdt.h:27
#define GDT_ENTRIES
number of entries in the GDT
Definition: gdt.h:12
A selector in the GDT.
Definition: gdt.c:31
void gdt_init()
Initializes the GDT.
Definition: gdt.c:72
void tss_init(gdt_entry_t *gdt)
Initializes the TSS.
Definition: tss.c:35
#define GDT_RING3_CODE_SEG
user code segment index
Definition: gdt.h:15
uint8_t gr
granularity
Definition: gdt.h:34
#define GDT_RING0_DATA_SEG
kernel data segment index
Definition: gdt.h:14
uint8_t base24_31
where the segment begins (byte 4)
Definition: gdt.h:35
An entry in the GDT.
Definition: gdt.h:20
uint16_t dpl
DPL needed to access this memory segment.
Definition: gdt.c:33
uint8_t sz
size
Definition: gdt.h:33
struct gdt_selector_t::@9 bits
bit field
uint32_t base0_23
where the segment begins (byte 1-3)
Definition: gdt.h:22
uint8_t ex
executable
Definition: gdt.h:26
uint16_t gdt_get_selector(size_t entry)
Returns a selector ready to be loaded in a segment register.
Definition: gdt.c:103
uint32_t base
where the GDT is located
Definition: gdt.c:26
uint8_t reserved
always 0 (long mode & available)
Definition: gdt.h:32
void tss_load()
Loads the TSS into the TR register.
Definition: tss.c:53
void gdt_flush()
Loads the kernel code and data segments into the segment registers.
static void gdt_load()
Loads the GDT into the GDTR register.
Definition: gdt.c:58
uint8_t rw
read / write allowed
Definition: gdt.h:24
uint16_t word
useful for casting
Definition: gdt.c:37
Definition: stdint.h:17
uint8_t limit16_19
maximum offset allowed (last nibble)
Definition: gdt.h:31
static idt_entry_t idt[IDT_ENTRIES]
The IDT itself.
Definition: idt.c:57
static gdt_entry_t gdt[GDT_ENTRIES]
The GDT itself. It is located inside the kernel.
Definition: gdt.c:41
void gdt_init_entry(size_t entry, uint32_t base, uint32_t limit)
Sets basic parameters of a GDT entry.
Definition: gdt.c:49
uint16_t limit
number of entries in the GDT
Definition: gdt.c:25
uint8_t pr
present
Definition: gdt.h:30
uint16_t limit0_15
maximum offset allowed (byte 1-2)
Definition: gdt.h:21
#define GDT_RING0_CODE_SEG
kernel code segment index
Definition: gdt.h:13