summaryrefslogtreecommitdiffstats
path: root/arch/x86/include/gdt.h
blob: c352f3233577f00cc8e027b2629b53ecd199a925 (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
#ifndef __X86_GDT_H
#define __X86_GDT_H

#include <stdint.h>

// Limit is 20-bit value
#define GDT_LIMIT_MAX		(0x000FFFFF)

// Flags (4 bits)
#define GDT_GRAN_4KB		(1 << 3)
#define GDT_GRAN_BYTE		(0 << 3) /*
					  * Granularity. Indicates the size the
					  * limit value is scaled by.
					  */
#define GDT_64BIT		(1 << 1)
#define GDT_32BIT		(1 << 2)
#define GDT_16BIT		(0 << 2)

// Access flags (8 bits)
#define GDT_ACCESS_ACC		(1 << 0) /*
					  * Accessed bit. The CPU sets 1 when
					  * the segment is accessed.
					  */
#define GDT_ACCESS_RW		(1 << 1) /*
					  * Readable/Writable bit.
					  *
					  * For code segments: readable bit.
					  *   If set 1 read access is allowed.
					  *   Write access is never allowed.
					  *
					  * For data segments: writable bit.
					  *   If set 1 write access is allowed.
					  *   Read access is always allowed.
					  */
#define GDT_ACCESS_DC		(1 << 2) /*
					  * Direction/Conforming bit.
					  *
					  */
#define GDT_ACCESS_EX		(1 << 3) /*
					  * Executable bit.
					  *   0 defines a data segment
					  *   1 defines a code segment
					  */
#define GDT_ACCESS_S		(1 << 4) /*
					  * Descriptor type bit.
					  *   0 defines a system segment (TSS, LDT)
					  *   1 defines a code/data segment
					  */
#define GDT_ACCESS_PL0		(0 << 5) /* the highest privilege */
#define GDT_ACCESS_PL1		(1 << 5)
#define GDT_ACCESS_PL2		(2 << 5)
#define GDT_ACCESS_PL3		(3 << 5) /* the lowest privilege */
#define GDT_ACCESS_PRESENT	(1 << 7) /* Must be set for any valid segments */

struct gdt_entry {
	uint16_t limit_low;
	uint16_t base_low;
	uint8_t base_middle;

	union {
		struct {
			uint8_t type : 4; // EX + DC + RW + ACC
			uint8_t s : 1;    // 0 = system desc, 1 = regular desc
			uint8_t dpl : 2;  // desc privilege level
			uint8_t p : 1;    // present
		};

		uint8_t access;
	};

	union {
		struct {
			uint8_t limit_hi : 4;
			uint8_t avl : 1; // available bit
			uint8_t l : 1;   // 64-bit segment
			uint8_t d : 1;   // default operation size. 0 = 16 bit, 1 = 32 bit
			uint8_t g : 1;   // granularity: 0 = byte, 1 = 4 KB
		};

		struct {
			uint8_t limit_high : 4;
			uint8_t flags : 4;
		};
	};

	uint8_t base_high;
} __attribute__((packed));

void init_segmentation(void);

#endif /* __X86_GDT_H */