Skip to content

Latest commit

 

History

History
375 lines (351 loc) · 11.4 KB

process.cpp

File metadata and controls

375 lines (351 loc) · 11.4 KB
 
Nov 7, 2016
Nov 7, 2016
1
// PhoeniX OS Process subsystem
Apr 25, 2017
Apr 25, 2017
2
// Copyright © 2017 Yury Popov a.k.a. PhoeniX
Aug 24, 2014
Aug 24, 2014
4
#include "process.hpp"
Nov 7, 2016
Nov 7, 2016
6
#include "processmanager.hpp"
Apr 25, 2017
Apr 25, 2017
7
#include "syscall.hpp"
May 26, 2019
May 26, 2019
8
#include "acpi.hpp"
Sep 1, 2014
Sep 1, 2014
9
May 14, 2019
May 14, 2019
10
11
using PTE = Pagetable::Entry;
May 26, 2019
May 26, 2019
12
13
14
15
16
Process::Process() :
id(uint64_t(-1)), entry(0),
_aslrCode(RAND::get<uintptr_t>(0x80000000llu, 0x100000000llu) << 12),
_aslrStack(RAND::get<uintptr_t>(0x40000000llu, 0x80000000llu) << 12),
_syscallPage(0), _syscallNum(0),
May 26, 2019
May 26, 2019
17
name(nullptr),
May 26, 2019
May 26, 2019
18
19
pagetable(nullptr) {
iomap[0] = iomap[1] = nullptr;
May 12, 2016
May 12, 2016
20
}
May 26, 2019
May 26, 2019
21
May 12, 2016
May 12, 2016
22
Process::~Process() {
May 23, 2019
May 23, 2019
23
void *rsp; asm volatile("mov %%rsp, %q0; and $~0xFFF, %q0":"=r"(rsp));
May 14, 2019
May 14, 2019
24
if (pagetable != nullptr) {
Sep 28, 2016
Sep 28, 2016
25
PTE addr;
May 14, 2019
May 14, 2019
26
for (uintptr_t ptx = 0; ptx < 512; ptx++) {
Sep 28, 2016
Sep 28, 2016
27
28
29
addr = pagetable[ptx];
if (!addr.present)
continue;
Nov 2, 2016
Nov 2, 2016
30
PTE *ppde = addr.getPTE();
May 14, 2019
May 14, 2019
31
for (uintptr_t pdx = 0; pdx < 512; pdx++) {
Sep 28, 2016
Sep 28, 2016
32
33
34
addr = ppde[pdx];
if (!addr.present)
continue;
Nov 2, 2016
Nov 2, 2016
35
PTE *pppde = addr.getPTE();
May 14, 2019
May 14, 2019
36
for (uintptr_t pdpx = 0; pdpx < 512; pdpx++) {
Sep 28, 2016
Sep 28, 2016
37
38
39
addr = pppde[pdpx];
if (!addr.present)
continue;
Nov 2, 2016
Nov 2, 2016
40
PTE *ppml4e = addr.getPTE();
May 14, 2019
May 14, 2019
41
for (uintptr_t pml4x = 0; pml4x < 512; pml4x++) {
Sep 28, 2016
Sep 28, 2016
42
43
44
addr = ppml4e[pml4x];
if (!addr.present)
continue;
Nov 2, 2016
Nov 2, 2016
45
void *page = addr.getPtr();
May 23, 2019
May 23, 2019
46
uintptr_t ptaddr = ((ptx << (12 + 9 + 9 + 9))
May 14, 2019
May 14, 2019
47
| (pdx << (12 + 9 + 9))
May 23, 2019
May 23, 2019
48
49
50
| (pdpx << (12 + 9)) | (pml4x << (12)));
if (page == rsp) continue;
if (uintptr_t(page) == ptaddr) continue;
Nov 7, 2016
Nov 7, 2016
51
Pagetable::free(page);
Sep 28, 2016
Sep 28, 2016
52
}
Nov 7, 2016
Nov 7, 2016
53
Pagetable::free(ppml4e);
Sep 28, 2016
Sep 28, 2016
54
}
Nov 7, 2016
Nov 7, 2016
55
Pagetable::free(pppde);
Sep 28, 2016
Sep 28, 2016
56
}
Nov 7, 2016
Nov 7, 2016
57
Pagetable::free(ppde);
Sep 28, 2016
Sep 28, 2016
58
}
Nov 7, 2016
Nov 7, 2016
59
Pagetable::free(pagetable);
Sep 28, 2016
Sep 28, 2016
60
}
Nov 2, 2016
Nov 2, 2016
61
62
for (size_t i = 0; i < symbols.getCount(); i++) {
delete[] symbols[i].name;
Sep 28, 2016
Sep 28, 2016
63
}
Nov 2, 2016
Nov 2, 2016
64
65
66
for (size_t i = 0; i < threads.getCount(); i++) {
ProcessManager::getManager()->dequeueThread(threads[i]);
delete threads[i];
Sep 28, 2016
Sep 28, 2016
67
}
May 26, 2019
May 26, 2019
68
delete name;
Sep 28, 2016
Sep 28, 2016
69
}
May 12, 2016
May 12, 2016
70
May 26, 2019
May 26, 2019
71
PTE* Process::addPage(uintptr_t vaddr, void* paddr, uint8_t flags) {
Sep 28, 2016
Sep 28, 2016
72
73
74
75
uint16_t ptx = (vaddr >> (12 + 9 + 9 + 9)) & 0x1FF;
uint16_t pdx = (vaddr >> (12 + 9 + 9)) & 0x1FF;
uint16_t pdpx = (vaddr >> (12 + 9)) & 0x1FF;
uint16_t pml4x = (vaddr >> (12)) & 0x1FF;
May 14, 2019
May 14, 2019
76
if (pagetable == nullptr) {
Nov 7, 2016
Nov 7, 2016
77
pagetable = static_cast<PTE*>(Pagetable::alloc());
May 14, 2019
May 14, 2019
78
addPage(uintptr_t(pagetable), pagetable, 5);
Sep 28, 2016
Sep 28, 2016
79
}
May 27, 2019
May 27, 2019
80
81
82
if (!pagetable[ptx].present) {
pagetable[ptx] = PTE(Pagetable::alloc(), 7);
addPage(pagetable[ptx].getUintPtr(), pagetable[ptx].getPtr(), 5);
Sep 28, 2016
Sep 28, 2016
83
}
May 27, 2019
May 27, 2019
84
85
86
87
PTE *pde = pagetable[ptx].getPTE();
if (!pde[pdx].present) {
pde[pdx] = PTE(Pagetable::alloc(), 7);
addPage(pde[pdx].getUintPtr(), pde[pdx].getPtr(), 5);
Sep 28, 2016
Sep 28, 2016
88
}
May 27, 2019
May 27, 2019
89
90
91
92
PTE *pdpe = pde[pdx].getPTE();
if (!pdpe[pdpx].present) {
pdpe[pdpx] = PTE(Pagetable::alloc(), 7);
addPage(pdpe[pdpx].getUintPtr(), pdpe[pdpx].getPtr(), 5);
Sep 28, 2016
Sep 28, 2016
93
}
May 27, 2019
May 27, 2019
94
95
PTE *pml4e = pdpe[pdpx].getPTE();
pml4e[pml4x] = PTE(paddr, flags | 1);
May 26, 2019
May 26, 2019
96
return &pml4e[pml4x];
May 12, 2016
May 12, 2016
97
98
99
}
uintptr_t Process::addSection(SectionType type, size_t size) {
Sep 28, 2016
Sep 28, 2016
100
101
102
if (size == 0)
return 0;
size_t pages = (size >> 12) + 1;
May 14, 2019
May 14, 2019
103
104
105
106
107
108
109
uintptr_t vaddr;
if (type != SectionTypeStack) {
vaddr = _aslrCode;
} else {
vaddr = _aslrStack;
}
Nov 14, 2016
Nov 14, 2016
110
for (uintptr_t caddr = vaddr; caddr < vaddr + size; caddr += 0x1000) {
May 14, 2019
May 14, 2019
111
if (getPhysicalAddress(vaddr) != nullptr) {
Sep 28, 2016
Sep 28, 2016
112
vaddr += 0x1000;
Nov 14, 2016
Nov 14, 2016
113
caddr = vaddr - 0x1000;
Sep 28, 2016
Sep 28, 2016
114
115
116
117
118
119
120
}
}
uintptr_t addr = vaddr;
while (pages-- > 0) {
uint8_t flags = 4;
switch (type) {
case SectionTypeCode:
Apr 23, 2017
Apr 23, 2017
121
case SectionTypeROData:
Sep 28, 2016
Sep 28, 2016
122
123
124
125
126
127
128
break;
case SectionTypeData:
case SectionTypeBSS:
case SectionTypeStack:
flags |= 2;
break;
}
May 26, 2019
May 26, 2019
129
addPage(vaddr, Pagetable::alloc(), flags)->nx = type != SectionTypeCode;
Sep 28, 2016
Sep 28, 2016
130
131
132
vaddr += 0x1000;
}
return addr;
May 12, 2016
May 12, 2016
133
134
}
void Process::addSymbol(const char *name, uintptr_t ptr) {
May 14, 2019
May 14, 2019
135
symbols.insert() = { ptr, klib::strdup(name) };
May 12, 2016
May 12, 2016
136
137
}
void Process::setEntryAddress(uintptr_t ptr) {
Sep 28, 2016
Sep 28, 2016
138
entry = ptr;
May 12, 2016
May 12, 2016
139
140
}
uintptr_t Process::getSymbolByName(const char* name) {
Nov 2, 2016
Nov 2, 2016
141
for (size_t i = 0; i < symbols.getCount(); i++) {
May 14, 2019
May 14, 2019
142
if (klib::strcmp(symbols[i].name, name) == 0)
Nov 2, 2016
Nov 2, 2016
143
return symbols[i].ptr;
Sep 28, 2016
Sep 28, 2016
144
145
}
return 0;
May 12, 2016
May 12, 2016
146
}
May 26, 2019
May 26, 2019
147
148
149
150
151
152
153
154
155
156
157
158
159
struct SyscallEntry {
const uint8_t _pre[2] = {
// movabsq ..., %rax
0x48, 0xb8,
};
const uint64_t syscall_id;
const uint8_t _post[3] = {
// syscallq; ret
0x0f, 0x05, 0xc3,
};
explicit SyscallEntry(uint64_t idx) : syscall_id(idx) {}
} PACKED;
Nov 3, 2016
Nov 3, 2016
160
uintptr_t Process::linkLibrary(const char* funcname) {
May 26, 2019
May 26, 2019
161
162
163
164
if (klib::strcmp(funcname, "kptr_acpi_rsdp") == 0) {
return uintptr_t(ACPI::getController()->getRSDPAddr());
}
Nov 3, 2016
Nov 3, 2016
165
166
167
uintptr_t ptr = getSymbolByName(funcname);
if (ptr != 0) return ptr;
Apr 25, 2017
Apr 25, 2017
168
169
uint64_t syscall_id;
if ((syscall_id = Syscall::callByName(funcname)) != 0) {
May 26, 2019
May 26, 2019
170
171
172
173
174
175
176
static const constexpr size_t countInPage = 0x1000 / sizeof(SyscallEntry);
if (_syscallPage == 0 || _syscallNum == countInPage) {
_syscallPage = addSection(SectionTypeCode, sizeof(SyscallEntry) * countInPage);
_syscallNum = 0;
}
struct SyscallEntry call(syscall_id);
ptr = _syscallPage + (_syscallNum++) * sizeof(SyscallEntry);
Apr 25, 2017
Apr 25, 2017
177
178
179
writeData(ptr, &call, sizeof(call));
addSymbol(funcname, ptr);
}
Nov 3, 2016
Nov 3, 2016
180
181
182
return ptr;
}
May 26, 2019
May 26, 2019
183
184
void Process::writeData(uintptr_t address, const void* src, size_t size) {
const uint8_t *ptr = static_cast<const uint8_t*>(src);
Sep 28, 2016
Sep 28, 2016
185
186
while (size > 0) {
void *dest = getPhysicalAddress(address);
May 14, 2019
May 14, 2019
187
size_t limit = 0x1000 - (uintptr_t(dest) & 0xFFF);
May 14, 2019
May 14, 2019
188
size_t count = klib::min(size, limit);
Nov 2, 2016
Nov 2, 2016
189
Memory::copy(dest, ptr, count);
Sep 28, 2016
Sep 28, 2016
190
size -= count;
Nov 2, 2016
Nov 2, 2016
191
ptr += count;
Sep 28, 2016
Sep 28, 2016
192
193
address += count;
}
May 12, 2016
May 12, 2016
194
}
May 14, 2019
May 14, 2019
195
void Process::readData(void* dst, uintptr_t address, size_t size) const {
Nov 2, 2016
Nov 2, 2016
196
char *ptr = static_cast<char*>(dst);
Sep 28, 2016
Sep 28, 2016
197
198
while (size > 0) {
void *src = getPhysicalAddress(address);
May 14, 2019
May 14, 2019
199
size_t limit = 0x1000 - (uintptr_t(src) & 0xFFF);
May 14, 2019
May 14, 2019
200
size_t count = klib::min(size, limit);
Nov 2, 2016
Nov 2, 2016
201
Memory::copy(ptr, src, count);
Sep 28, 2016
Sep 28, 2016
202
size -= count;
Nov 2, 2016
Nov 2, 2016
203
ptr += count;
Sep 28, 2016
Sep 28, 2016
204
205
address += count;
}
May 12, 2016
May 12, 2016
206
}
May 14, 2019
May 14, 2019
207
char *Process::readString(uintptr_t address) const {
Sep 28, 2016
Sep 28, 2016
208
size_t length = 0;
Nov 2, 2016
Nov 2, 2016
209
const char *src = static_cast<const char*>(getPhysicalAddress(address));
May 14, 2019
May 14, 2019
210
size_t limit = 0x1000 - (uintptr_t(src) & 0xFFF);
Sep 28, 2016
Sep 28, 2016
211
212
213
while (limit-- && src[length] != 0) {
length++;
if (limit == 0) {
Nov 2, 2016
Nov 2, 2016
214
src = static_cast<const char*>(getPhysicalAddress(address + length));
Sep 28, 2016
Sep 28, 2016
215
216
217
218
limit += 0x1000;
}
}
if (length == 0)
May 14, 2019
May 14, 2019
219
return nullptr;
Nov 2, 2016
Nov 2, 2016
220
char *buf = new char[length + 1]();
Sep 28, 2016
Sep 28, 2016
221
222
readData(buf, address, length + 1);
return buf;
May 12, 2016
May 12, 2016
223
}
May 14, 2019
May 14, 2019
224
void *Process::getPhysicalAddress(uintptr_t ptr) const {
May 14, 2019
May 14, 2019
225
226
if (pagetable == nullptr)
return nullptr;
Sep 28, 2016
Sep 28, 2016
227
uintptr_t off = ptr & 0xFFF;
Nov 7, 2016
Nov 7, 2016
228
PTE *addr = PTE::find(ptr, pagetable);
May 14, 2019
May 14, 2019
229
if (!addr || !addr->present) return nullptr;
Nov 7, 2016
Nov 7, 2016
230
return reinterpret_cast<void*>(addr->getUintPtr() + off);
May 12, 2016
May 12, 2016
231
232
}
void Process::addThread(Thread *thread, bool suspended) {
Sep 28, 2016
Sep 28, 2016
233
234
235
236
if (thread->stack_top == 0) {
thread->stack_top = addSection(SectionTypeStack, 0x7FFF) + 0x8000;
thread->regs.rsp = thread->stack_top;
}
May 14, 2019
May 14, 2019
237
thread->suspend_ticks = suspended ? uint64_t(-1) : 0;
Sep 28, 2016
Sep 28, 2016
238
Nov 2, 2016
Nov 2, 2016
239
threads.add(thread);
Sep 28, 2016
Sep 28, 2016
240
ProcessManager::getManager()->queueThread(this, thread);
May 13, 2016
May 13, 2016
241
}
May 18, 2019
May 18, 2019
242
243
244
245
246
247
248
249
250
251
252
253
254
255
void Process::allowIOPorts(uint16_t min, uint16_t max) {
for (uint16_t i = 0; i <= (max - min); i++) {
uint16_t port = min + i;
size_t space = port / 8 / 0x1000;
size_t byte = (port / 8) & 0xFFF;
size_t bit = port % 8;
uint8_t *map;
if (!(map = reinterpret_cast<uint8_t*>(iomap[space]))) {
map = reinterpret_cast<uint8_t*>(iomap[space] = Pagetable::alloc());
Memory::fill(map, 0xFF, 0x1000);
}
map[byte] &= ~(1 << bit);
}
}
May 12, 2016
May 12, 2016
256
void Process::startup() {
May 14, 2019
May 14, 2019
257
258
DTREG gdt = { 0, nullptr };
DTREG idt = { 0, nullptr };
Nov 1, 2016
Nov 1, 2016
259
asm volatile("sgdtq %0; sidtq %1":"=m"(gdt), "=m"(idt));
Sep 28, 2016
Sep 28, 2016
260
Nov 1, 2016
Nov 1, 2016
261
static const uintptr_t KB4 = 0xFFFFFFFFFFFFF000;
May 14, 2019
May 14, 2019
262
263
for (uintptr_t addr = uintptr_t(gdt.addr) & KB4;
addr < (uintptr_t(gdt.addr) + gdt.limit); addr += 0x1000) {
May 23, 2019
May 23, 2019
264
addPage(addr, reinterpret_cast<void*>(addr), 1);
Nov 1, 2016
Nov 1, 2016
265
}
May 14, 2019
May 14, 2019
266
267
for (uintptr_t addr = uintptr_t(idt.addr) & KB4;
addr < (uintptr_t(idt.addr) + idt.limit); addr += 0x1000) {
May 23, 2019
May 23, 2019
268
addPage(addr, reinterpret_cast<void*>(addr), 1);
Nov 1, 2016
Nov 1, 2016
269
}
May 14, 2019
May 14, 2019
270
Interrupts::REC64 *recs = static_cast<Interrupts::REC64*>(idt.addr);
Nov 1, 2016
Nov 1, 2016
271
272
uintptr_t page = 0;
for (uint16_t i = 0; i < 0x100; i++) {
May 14, 2019
May 14, 2019
273
274
275
uintptr_t handler = (uintptr_t(recs[i].offset_low)
| (uintptr_t(recs[i].offset_middle) << 16)
| (uintptr_t(recs[i].offset_high) << 32));
Nov 1, 2016
Nov 1, 2016
276
277
if (page != (handler & KB4)) {
page = handler & KB4;
May 23, 2019
May 23, 2019
278
addPage(page, reinterpret_cast<void*>(page), 1);
Nov 1, 2016
Nov 1, 2016
279
280
}
}
Apr 23, 2017
Apr 23, 2017
281
uintptr_t handler, sc_wrapper;
Nov 16, 2016
Nov 16, 2016
282
asm volatile("lea __interrupt_wrap(%%rip), %q0":"=r"(handler));
Apr 23, 2017
Apr 23, 2017
283
asm volatile("lea _ZN7Syscall7wrapperEv(%%rip), %q0":"=r"(sc_wrapper));
Nov 16, 2016
Nov 16, 2016
284
handler &= KB4;
Apr 23, 2017
Apr 23, 2017
285
sc_wrapper &= KB4;
May 23, 2019
May 23, 2019
286
addPage(handler, reinterpret_cast<void*>(handler), 1);
May 26, 2019
May 26, 2019
287
addPage(handler + 0x1000, reinterpret_cast<void*>(handler + 0x1000), 1);
May 23, 2019
May 23, 2019
288
addPage(sc_wrapper, reinterpret_cast<void*>(sc_wrapper), 1);
May 26, 2019
May 26, 2019
289
addPage(sc_wrapper + 0x1000, reinterpret_cast<void*>(sc_wrapper + 0x1000), 1);
May 14, 2019
May 14, 2019
290
291
GDT::Entry *gdt_ent = reinterpret_cast<GDT::Entry*>(uintptr_t(gdt.addr) + 8 * 3);
GDT::Entry *gdt_top = reinterpret_cast<GDT::Entry*>(uintptr_t(gdt.addr) + gdt.limit);
May 14, 2019
May 14, 2019
292
May 18, 2019
May 18, 2019
293
294
295
296
297
298
299
300
if (!iomap[0]) {
iomap[0] = Pagetable::alloc();
Memory::fill(iomap[0], 0xFF, 0x1000);
}
if (!iomap[1]) {
iomap[1] = Pagetable::alloc();
Memory::fill(iomap[1], 0xFF, 0x1000);
}
May 14, 2019
May 14, 2019
301
Nov 1, 2016
Nov 1, 2016
302
while (gdt_ent < gdt_top) {
Nov 2, 2016
Nov 2, 2016
303
uintptr_t base = gdt_ent->getBase();
May 27, 2019
May 27, 2019
304
if ((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) {
Sep 28, 2016
Sep 28, 2016
305
gdt_ent++;
Nov 1, 2016
Nov 1, 2016
306
continue;
Sep 28, 2016
Sep 28, 2016
307
}
May 23, 2019
May 23, 2019
308
309
310
311
GDT::SystemEntry *sysent = reinterpret_cast<GDT::SystemEntry*>(gdt_ent);
base = sysent->getBase();
Nov 1, 2016
Nov 1, 2016
312
uintptr_t page = base & KB4;
May 23, 2019
May 23, 2019
313
314
315
addPage(page, reinterpret_cast<void*>(page), 1);
addPage(page + 0x1000, iomap[0], 1);
addPage(page + 0x2000, iomap[1], 1);
Nov 1, 2016
Nov 1, 2016
316
Nov 2, 2016
Nov 2, 2016
317
TSS64_ENT *tss = reinterpret_cast<TSS64_ENT*>(base);
Nov 1, 2016
Nov 1, 2016
318
319
uintptr_t stack = tss->ist[0];
page = stack - 0x1000;
May 23, 2019
May 23, 2019
320
addPage(page, reinterpret_cast<void*>(page), 3);
May 14, 2019
May 14, 2019
321
gdt_ent = reinterpret_cast<GDT::Entry*>(sysent + 1);
Nov 1, 2016
Nov 1, 2016
322
323
}
Sep 28, 2016
Sep 28, 2016
324
325
326
Thread *thread = new Thread();
thread->regs.rip = entry;
thread->regs.rflags = 0;
May 27, 2019
May 27, 2019
327
id = (ProcessManager::getManager())->registerProcess(this);
Sep 28, 2016
Sep 28, 2016
328
addThread(thread, false);
May 12, 2016
May 12, 2016
329
}
Apr 25, 2017
Apr 25, 2017
330
331
void Process::exit(int code) {
May 26, 2019
May 26, 2019
332
(void)code; // TODO: handle
Apr 25, 2017
Apr 25, 2017
333
334
335
for (size_t i = 0; i < threads.getCount(); i++) {
ProcessManager::getManager()->dequeueThread(threads[i]);
}
May 27, 2019
May 27, 2019
336
ProcessManager::getManager()->exitProcess(this, code);
Apr 25, 2017
Apr 25, 2017
337
338
delete this;
}
May 14, 2019
May 14, 2019
339
May 26, 2019
May 26, 2019
340
341
342
343
344
345
const char *Process::getName() const { return name; }
void Process::setName(const char *newname) {
delete name;
name = newname ? klib::strdup(newname) : nullptr;
}
May 14, 2019
May 14, 2019
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
void Process::print_stacktrace(uintptr_t base, const Process *process) {
struct stackframe {
struct stackframe* rbp;
uintptr_t rip;
} __attribute__((packed));
printf("STACK TRACE:");
struct stackframe tmpframe;
const struct stackframe *frame;
if (base) {
frame = reinterpret_cast<struct stackframe*>(base);
} else {
asm volatile("mov %%rbp, %q0":"=r"(frame)::);
}
size_t lim = 10;
May 14, 2019
May 14, 2019
361
while (lim-- && frame != nullptr) {
May 14, 2019
May 14, 2019
362
363
364
365
366
367
368
369
370
371
372
373
374
375
if (process) {
process->readData(&tmpframe.rbp, uintptr_t(frame), sizeof(uintptr_t));
if (tmpframe.rbp) {
process->readData(&tmpframe.rip, uintptr_t(frame)+sizeof(uintptr_t), sizeof(uintptr_t));
} else {
break;
}
frame = &tmpframe;
}
printf(" [%p]:%p", frame->rbp, reinterpret_cast<void*>(frame->rip));
frame = frame->rbp;
}
printf("\n");
}