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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
#pragma once
#include "types.h"
#define PAGE_SIZE 4096u
union Descriptor {
struct {
WORD limit_lo;
WORD base_lo;
BYTE base_hi;
BYTE type : 4;
BYTE descriptor_type : 1;
BYTE dpl : 2;
BYTE segment_present : 1;
BYTE limit_hi : 4;
BYTE : 1;
BYTE zero : 1;
BYTE operation_size : 1;
BYTE granularity : 1;
BYTE base_hi2;
};
struct {
DWORD low;
DWORD high;
};
enum Type {
Invalid = 0,
AvailableTSS_16bit = 0x1,
LDT = 0x2,
BusyTSS_16bit = 0x3,
CallGate_16bit = 0x4,
TaskGate = 0x5,
InterruptGate_16bit = 0x6,
TrapGate_16bit = 0x7,
AvailableTSS_32bit = 0x9,
BusyTSS_32bit = 0xb,
CallGate_32bit = 0xc,
InterruptGate_32bit = 0xe,
TrapGate_32bit = 0xf,
};
void setBase(void* b)
{
base_lo = (DWORD)(b) & 0xffff;
base_hi = ((DWORD)(b) >> 16) & 0xff;
base_hi2 = ((DWORD)(b) >> 24) & 0xff;
}
void setLimit(DWORD l)
{
limit_lo = (DWORD)l & 0xffff;
limit_hi = ((DWORD)l >> 16) & 0xff;
}
} PACKED;
class IRQHandler;
void gdt_init();
void idt_init();
void registerInterruptHandler(BYTE number, void (*f)());
void registerUserCallableInterruptHandler(BYTE number, void (*f)());
void registerIRQHandler(BYTE number, IRQHandler&);
void unregisterIRQHandler(BYTE number, IRQHandler&);
void flushIDT();
void flushGDT();
void loadTaskRegister(WORD selector);
word gdt_alloc_entry();
void gdt_free_entry(word);
Descriptor& getGDTEntry(WORD selector);
void writeGDTEntry(WORD selector, Descriptor&);
#define HANG asm volatile( "cli; hlt" );
#define LSW(x) ((DWORD)(x) & 0xFFFF)
#define MSW(x) (((DWORD)(x) >> 16) & 0xFFFF)
#define LSB(x) ((x) & 0xFF)
#define MSB(x) (((x)>>8) & 0xFF)
#define cli() asm volatile("cli")
#define sti() asm volatile("sti")
static inline dword cpuFlags()
{
dword flags;
asm volatile(
"pushf\n"
"pop %0\n"
:"=rm"(flags)
::"memory");
return flags;
}
class InterruptDisabler {
public:
InterruptDisabler()
{
m_flags = cpuFlags();
cli();
}
~InterruptDisabler()
{
if (m_flags & 0x200)
sti();
}
private:
dword m_flags;
};
/* Map IRQ0-15 @ ISR 0x50-0x5F */
#define IRQ_VECTOR_BASE 0x50
struct PageFaultFlags {
enum Flags {
NotPresent = 0x00,
ProtectionViolation = 0x01,
Read = 0x00,
Write = 0x02,
UserMode = 0x04,
SupervisorMode = 0x00,
InstructionFetch = 0x08,
};
};
class PageFault {
public:
PageFault(word code, LinearAddress address)
: m_code(code)
, m_address(address)
{
}
LinearAddress address() const { return m_address; }
word code() const { return m_code; }
bool isNotPresent() const { return (m_code & 1) == PageFaultFlags::NotPresent; }
bool isProtectionViolation() const { return (m_code & 1) == PageFaultFlags::ProtectionViolation; }
bool isRead() const { return (m_code & 2) == PageFaultFlags::Read; }
bool isWrite() const { return (m_code & 2) == PageFaultFlags::Write; }
bool isUser() const { return (m_code & 4) == PageFaultFlags::UserMode; }
bool isSupervisor() const { return (m_code & 4) == PageFaultFlags::SupervisorMode; }
bool isInstructionFetch() const { return (m_code & 8) == PageFaultFlags::InstructionFetch; }
private:
word m_code;
LinearAddress m_address;
};
struct RegisterDump {
WORD ss;
WORD gs;
WORD fs;
WORD es;
WORD ds;
DWORD edi;
DWORD esi;
DWORD ebp;
DWORD esp;
DWORD ebx;
DWORD edx;
DWORD ecx;
DWORD eax;
DWORD eip;
WORD cs;
WORD __csPadding;
DWORD eflags;
DWORD esp_if_crossRing;
WORD ss_if_crossRing;
} PACKED;
inline constexpr dword pageBaseOf(dword address)
{
return address & 0xfffff000;
}
class CPUID {
public:
CPUID(dword function) { asm volatile("cpuid" : "=a" (m_eax), "=b" (m_ebx), "=c" (m_ecx), "=d" (m_edx) : "a" (function), "c" (0)); }
dword eax() const { return m_eax; }
dword ebx() const { return m_ebx; }
dword ecx() const { return m_ecx; }
dword edx() const { return m_edx; }
private:
dword m_eax { 0xffffffff };
dword m_ebx { 0xffffffff };
dword m_ecx { 0xffffffff };
dword m_edx { 0xffffffff };
};
|