...
 
Commits (16)
......@@ -5,7 +5,12 @@
#include "efi.hpp"
#include "multiboot_info.hpp"
#include "pagetable.hpp"
#include "font-8x16.hpp"
asm(
".rodata;"
"fb_font_8x16:"
".incbin \"" __FILE__ ".font.psf\""
);
class ConsoleDisplay: public Display {
private:
......@@ -62,6 +67,7 @@ class FramebufferDisplay: public Display {
size_t width, height;
PixelFormat pixelFormat;
size_t offset;
const uint8_t *fb_font_8x16;
size_t pixelBytes() {
switch (pixelFormat) {
......@@ -81,7 +87,7 @@ class FramebufferDisplay: public Display {
} else if (c == '\t') {
offset += 8 - ((offset % charWidth()) % 8);
} else {
const uint8_t *fontsym = fb_font_8x16 + (size_t(c) * 16);
const uint8_t *fontsym = fb_font_8x16 + (size_t(uint8_t(c)) * 16);
size_t offsetX = offset % charWidth();
size_t offsetY = offset / charWidth();
size_t pb = pixelBytes();
......@@ -126,6 +132,7 @@ class FramebufferDisplay: public Display {
Pagetable::map(reinterpret_cast<void*>(ptr));
}
clean();
asm volatile("lea fb_font_8x16(%%rip), %q0":"=r"(fb_font_8x16));
}
void write(const char *str) {
Mutex::CriticalLock lock(mutex);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
// PhoeniX OS Stub hello module
// Copyright © 2019 Yury Popov a.k.a. PhoeniX
#include "kernmod.hpp"
MODDESC(name, "Driver/ACPI");
MODDESC(version, "1.0");
MODDESC(description, "Generic ACPI Driver");
MODDESC(requirements, "");
MODDESC(developer, "PhoeniX");
template<typename T>
static inline size_t putn(T x, uint8_t base = 10, size_t len = 1) {
char buf[sizeof(T) * 4];
size_t sz = sizeof(buf) - 1, off = sz;
buf[off] = 0;
while (off >= sz + 1 - len || x > 0) {
uint8_t c = uint8_t(x % base); x /= base;
buf[--off] = (c < 10) ? static_cast<char>('0' + c) : static_cast<char>('a' - 10 + c);
}
puts(buf + off);
return sz - off;
}
namespace ACPI {
struct RSDP {
static const uint64_t SIG = 0x2052545020445352; // 'RSD PTR '
uint64_t sig;
uint8_t crc;
char oem[6];
uint8_t rev;
uintptr_t rsdt:32;
inline bool _isValid0() const {
if (sig != SIG) return 0;
uint8_t sum = 0;
const uint8_t *buf = reinterpret_cast<const uint8_t*>(this);
for (size_t i = 0; i < sizeof(RSDP); i++) sum += buf[i];
if (sum != 0) return 0;
return 1;
}
inline bool isValid0() const {
return rev == 0 && _isValid0();
}
} __attribute__((packed));
struct RSDPv20 : RSDP {
size_t size:32;
uintptr_t xsdt;
uint8_t extcrc;
uint8_t rsvd[3];
inline bool isValid2() const {
if (!RSDP::_isValid0()) return 0;
if (rev == 0) return 0;
uint8_t sum = 0;
const uint8_t *buf = reinterpret_cast<const uint8_t*>(this);
for (size_t i = 0; i < sizeof(RSDPv20); i++) sum += buf[i];
if (sum != 0) return 0;
return 1;
}
} __attribute__((packed));
struct SDT {
uint32_t sig;
uint32_t size;
uint8_t rev;
uint8_t crc;
char oemid[6];
char oemtblid[8];
uint32_t oemrev;
uint32_t crid;
uint32_t crrev;
inline bool isValid() const {
uint8_t sum = 0;
const uint8_t *buf = reinterpret_cast<const uint8_t*>(this);
for (size_t i = 0; i < size; i++) sum += buf[i];
return sum == 0;
}
inline size_t data_size() const {
return size - sizeof(SDT);
}
} __attribute__((packed));
struct RSDT : SDT {
static const uint32_t SIG = 0x54445352;
uint32_t ptrs[];
inline size_t count() const {
return SDT::data_size() / sizeof(*ptrs);
}
} __attribute__((packed));
struct XSDT : SDT {
static const uint32_t SIG = 0x54445358;
uint64_t ptrs[];
inline size_t count() const {
return SDT::data_size() / sizeof(*ptrs);
}
} __attribute__((packed));
static void parseDT(const void *addr) {
SDT desc;
kread(&desc, addr, sizeof(desc));
char path[] = "acpi/table.XXXX";
path[11] = static_cast<char>((desc.sig >> 0) & 0xFF);
path[12] = static_cast<char>((desc.sig >> 8) & 0xFF);
path[13] = static_cast<char>((desc.sig >> 16) & 0xFF);
path[14] = static_cast<char>((desc.sig >> 24) & 0xFF);
ioprovide(path, addr);
}
static void parseXSDT(const void *addr) {
XSDT desc;
kread(&desc, addr, sizeof(desc));
if (desc.sig != XSDT::SIG) return;
XSDT *xsdt = reinterpret_cast<XSDT*>(__builtin_alloca(desc.size));
kread(xsdt, addr, desc.size);
if (!xsdt->isValid()) return;
for (size_t i = 0; i < xsdt->count(); i++) {
parseDT(reinterpret_cast<const void*>(xsdt->ptrs[i]));
}
}
static void parseRSDT(const void *addr) {
RSDT desc;
kread(&desc, addr, sizeof(desc));
if (desc.sig != RSDT::SIG) return;
RSDT *rsdt = reinterpret_cast<RSDT*>(__builtin_alloca(desc.size));
kread(rsdt, addr, desc.size);
if (!rsdt->isValid()) return;
for (size_t i = 0; i < rsdt->count(); i++) {
parseDT(reinterpret_cast<const void*>(uintptr_t(rsdt->ptrs[i])));
}
}
static void parseRSDP(const void *addr) {
RSDPv20 desc;
kread(&desc, addr, sizeof(desc));
if (desc.isValid2()) {
parseXSDT(reinterpret_cast<const void*>(desc.xsdt));
} else if (desc.isValid0()) {
parseRSDT(reinterpret_cast<const void*>(desc.rsdt));
}
}
} // namespace ACPI
extern "C" {
extern const char __attribute__((weak)) kptr_acpi_rsdp[];
};
void module() {
if (kptr_acpi_rsdp == nullptr) {
puts("No ACPI RSDP\n");
} else {
ACPI::parseRSDP(kptr_acpi_rsdp);
}
exit(0);
}
......@@ -9,30 +9,32 @@ MODDESC(description, "Generic PCI Driver");
MODDESC(requirements, "port/CF8-CFF");
MODDESC(developer, "PhoeniX");
static inline void putl(uint32_t l) {
char buf[11];
int off = 10;
template<typename T>
static inline size_t putn(T x, uint8_t base = 10, size_t len = 1) {
char buf[sizeof(T) * 4];
size_t sz = sizeof(buf) - 1, off = sz;
buf[off] = 0;
while (off == 10 || l > 0) {
buf[--off] = '0' + (l % 10);
l /= 10;
while (off >= sz + 1 - len || x > 0) {
uint8_t c = uint8_t(x % base); x /= base;
buf[--off] = (c < 10) ? static_cast<char>('0' + c) : static_cast<char>('a' - 10 + c);
}
puts(buf + off);
return sz - off;
}
static inline void putx(uint32_t l) {
char buf[9];
int off = 8;
template<typename T>
static inline size_t sputn(char *out, T x, uint8_t base = 10, size_t len = 1) {
char buf[sizeof(T) * 4];
size_t sz = sizeof(buf) - 1, off = sz;
buf[off] = 0;
while (off == 8 || l > 0) {
char c = static_cast<char>(l & 0xF);
buf[--off] = (c < 10) ? ('0' + c) : ('a' + c - 10);
l /= 16;
c = static_cast<char>(l & 0xF);
buf[--off] = (c < 10) ? ('0' + c) : ('a' + c - 10);
l /= 16;
while (off >= sz + 1 - len || x > 0) {
uint8_t c = uint8_t(x % base); x /= base;
buf[--off] = (c < 10) ? static_cast<char>('0' + c) : static_cast<char>('a' - 10 + c);
}
puts(buf + off);
char *o = out, *p = buf + off;
while (*p != 0) *(o++) = *(p++);
*(o++) = 0;
return sz - off;
}
namespace PCI {
......@@ -125,13 +127,39 @@ namespace PCI {
uint8_t subClass = Device::getSubClass(bus, device, function);
uint8_t progIf = Device::getProgIf(bus, device, function);
uint8_t rev = Device::getRevision(bus, device, function);
puts("TODO: Provide device: ");
uint16_t vendorID = Device::getVendorID(bus, device, function);
uint16_t vendorId = Device::getVendorID(bus, device, function);
uint16_t deviceId = Device::getDeviceID(bus, device, function);
putl(bus); puts("."); putl(device); puts("."); putl(function); puts(" => ");
puts("["); putx(uint32_t(baseClass << 8) | subClass); puts("."); putx(progIf); puts("."); putx(rev); puts("]");
putx(vendorID); puts("."); putx(deviceId);
puts("\n");
uintptr_t address = 0x80000000u |
(uint32_t(bus) << 16) |
(uint32_t(device) << 11) |
(uint32_t(function) << 8);
const void *ptr = reinterpret_cast<const void*>(address);
{
char path[] = "pci/path.000.000.000.000";
char *p = path + 9;
p += sputn(p, bus); *(p++) = '.';
p += sputn(p, device); *(p++) = '.';
p += sputn(p, function); *(p++) = 0;
ioprovide(path, ptr);
}
{
char path[] = "pci/class.00.00.00.00";
char *p = path + 10;
p += sputn(p, baseClass, 16, 2); *(p++) = '.';
p += sputn(p, subClass, 16, 2); *(p++) = '.';
p += sputn(p, progIf, 16, 2); *(p++) = 0;
ioprovide(path, ptr);
}
{
char path[] = "pci/vendor.0000/device.0000/rev.00";
char *p = path + 11;
p += sputn(p, vendorId, 16, 4); *(p++) = '/'; p += 7;
p += sputn(p, deviceId, 16, 4); *(p++) = '/'; p += 4;
p += sputn(p, rev, 16, 2); *(p++) = 0;
ioprovide(path, ptr);
}
}
static void scanBus(uint8_t bus);
static void scanFunction(uint8_t bus, uint8_t device, uint8_t function) {
......
......@@ -14,6 +14,10 @@ extern "C" {
void puts(const char *);
void exit(int);
void kread(void *, const void *, size_t);
void ioprovide(const char *, const void *);
// Entry point
void module();
}
......@@ -158,6 +158,8 @@ bool ACPI::ParseRsdp(const void *ptr) {
if (sum)
return false;
rsdpAddr = ptr;
char oem[7];
Memory::copy(oem, p + 9, 6);
oem[6] = 0;
......@@ -240,6 +242,9 @@ ACPI::IOApicRedir ACPI::IOapicReadMap(uint32_t idx) {
a.raw[1] = IOapicIn(IOAPIC_REDTBL + idx * 2 + 1);
return a;
}
const void* ACPI::getRSDPAddr() {
return rsdpAddr;
}
void* ACPI::getLapicAddr() {
return localApicAddr;
}
......
......@@ -108,6 +108,7 @@ class ACPI {
static volatile ACPI *controller;
char *localApicAddr, *ioApicAddr;
const void *rsdpAddr;
uint8_t ioApicMaxCount;
uint32_t acpiCpuIds[256];
uint8_t acpiCpuCount;
......@@ -126,6 +127,7 @@ class ACPI {
static ACPI* getController();
uint32_t getLapicID();
uint32_t getCPUID();
const void* getRSDPAddr() PURE;
void* getLapicAddr() PURE;
uint32_t getCPUCount() PURE;
uint32_t getActiveCPUCount() PURE;
......
......@@ -22,21 +22,22 @@ class Pagetable {
} PACKED;
bool rsvd:1;
uint8_t avl :3;
uintptr_t _ptr :52;
uintptr_t _ptr :51;
uint8_t nx :1;
uintptr_t getUintPtr() { return _ptr << 12; }
void *getPtr() { return reinterpret_cast<void*>(getUintPtr()); }
Entry *getPTE() { return static_cast<Entry*>(getPtr()); }
Entry(): flags(0), rsvd(0), avl(0), _ptr(0) {}
Entry(): flags(0), rsvd(0), avl(0), _ptr(0), nx(0) {}
Entry(uintptr_t ptr, uint8_t avl, uint8_t flags):
flags(flags), rsvd(0), avl(avl), _ptr(ptr >> 12) {}
flags(flags), rsvd(0), avl(avl), _ptr(ptr >> 12), nx(0) {}
Entry(uintptr_t ptr, uint8_t flags):
flags(flags), rsvd(0), avl(0), _ptr(ptr >> 12) {}
flags(flags), rsvd(0), avl(0), _ptr(ptr >> 12), nx(0) {}
Entry(const void *ptr, uint8_t avl, uint8_t flags):
flags(flags), rsvd(0), avl(avl), _ptr(uintptr_t(ptr) >> 12) {}
flags(flags), rsvd(0), avl(avl), _ptr(uintptr_t(ptr) >> 12), nx(0) {}
Entry(const void *ptr, uint8_t flags):
flags(flags), rsvd(0), avl(0), _ptr(uintptr_t(ptr) >> 12) {}
flags(flags), rsvd(0), avl(0), _ptr(uintptr_t(ptr) >> 12), nx(0) {}
static Entry* find(uintptr_t ptr, Entry *pagetable) {
uint16_t ptx = (ptr >> (12 + 9 + 9 + 9)) & 0x1FF;
......
......@@ -201,17 +201,18 @@ void Interrupts::print(uint8_t num, CallbackRegs *regs, uint32_t code, const Pro
rflags_buf[1] = 'D';
if (regs->rflags & (1 << 11))
rflags_buf[0] = 'O';
uint64_t base; asm volatile("lea __text_start__(%%rip), %q0":"=r"(base));
printf("\n%s fault %s (cpu=%u, error=0x%x)\n"
"IP=%016lx CS=%04hx SS=%04hx DPL=%hhu\n"
"FL=%016lx [%s]\n"
"BASE=%016lx CS=%04hx SS=%04hx DPL=%hhu\n"
"IP=%016lx FL=%016lx [%s]\n"
"SP=%016lx BP=%016lx CR2=%08lx\n"
"SI=%016lx DI=%016lx\n"
"A =%016lx C =%016lx D =%016lx B =%016lx\n"
"8 =%016lx 9 =%016lx 10=%016lx 11=%016lx\n"
"12=%016lx 13=%016lx 14=%016lx 15=%016lx\n",
regs->dpl ? "Userspace" : "Kernel", FAULTS[num].code, cpuid, code,
regs->rip, regs->cs, regs->ss, regs->dpl,
regs->rflags, rflags_buf,
base, regs->cs, regs->ss, regs->dpl,
regs->rip, regs->rflags, rflags_buf,
regs->rsp, regs->rbp, cr2,
regs->rsi, regs->rdi,
regs->rax, regs->rcx, regs->rdx, regs->rbx,
......
......@@ -3,6 +3,7 @@
#include "syscall.hpp"
#include "processmanager.hpp"
#include "pagetable.hpp"
#include "./syscall_hash.hpp"
#include "./syscall_setup.hpp"
......@@ -28,6 +29,21 @@ static void syscall_exit(int code) {
);
}
static void syscall_kread(void *out, const void *kaddr, size_t size) {
Process *process = ProcessManager::getManager()->currentProcess();
for (size_t p = 0; p < size; p += 0x1000) {
Pagetable::map(reinterpret_cast<const void*>(uintptr_t(kaddr) + p));
}
process->writeData(uintptr_t(out), kaddr, size);
}
static void syscall_ioprovide(const char *path, const void *ptr) {
Process *process = ProcessManager::getManager()->currentProcess();
char *str = process->readString(uintptr_t(path));
printf("ioprovide [%s(%#lx) / %p] [%s]\n", process->getName(), process->getId(), ptr, str);
delete str;
}
#define SYSCALL_ENT(name) { \
syscall_hash(#name), \
reinterpret_cast<void*>(syscall_ ## name) \
......@@ -39,6 +55,8 @@ static const struct {
} PACKED syscall_map[] = {
SYSCALL_ENT(puts),
SYSCALL_ENT(exit),
SYSCALL_ENT(kread),
SYSCALL_ENT(ioprovide),
{0, nullptr}
};
......@@ -61,56 +79,51 @@ uint64_t Syscall::callByName(const char *name) {
void __attribute((naked)) Syscall::wrapper() {
asm volatile(
// Save registers
"push %rax;"
"push %rcx;"
"push %rdx;"
"push %rbx;"
"push %rbp;"
"push %rsi;"
"push %rdi;"
"push %r8;"
"push %r9;"
"push %r10;"
"push %r11;"
"push %r12;"
"push %r13;"
"push %r14;"
"push %r15;"
// Save pagetable & stack
"mov %cr3, %rax; mov %rsp, %rbx; push %rax; push %rbx;"
// Save pagetable
"mov %cr3, %rbx;"
// Set stack to absolute address
"sub $16, %rbx; ror $48, %rbx;"
"mov $4, %rcx;"
"1:"
"rol $9, %rbx;"
"mov %rbx, %rdx;"
"and $0x1FF, %rdx;"
"mov (%rax,%rdx,8), %rax;"
"and $~0xFFF, %rax;"
"loop 1b;"
"rol $12, %rbx; and $0xFFF, %rbx; add %rax, %rbx; mov %rbx, %rsp;"
"mov %rsp, %r12; shr $39, %r12; and $0x1FF, %r12;" // r12 = ptx
"mov (%rbx,%r12,8), %r13; and $~0xFFF, %r13; btr $63, %r13;" // rbx = pt, r12 = pte
"mov %rsp, %r12; shr $30, %r12; and $0x1FF, %r12;" // r12 = pdx
"mov (%r13,%r12,8), %r13; and $~0xFFF, %r13; btr $63, %r13;" // r13 = pde
"mov %rsp, %r12; shr $21, %r12; and $0x1FF, %r12;" // r12 = pdpx
"mov (%r13,%r12,8), %r13; and $~0xFFF, %r13; btr $63, %r13;" // r13 = pdpe
"mov %rsp, %r12; shr $12, %r12; and $0x1FF, %r12;" // r12 = pml4x
"mov (%r13,%r12,8), %r13; and $~0xFFF, %r13; btr $63, %r13;" // r13 = pml4e
// Save stack
"mov %rsp, %r12;"
"mov %rsp, %r14; and $0xFFF, %r14; add %r14, %r13; mov %r13, %rsp;"
// Set kernel pagetable
"_wrapper_mov_cr3: movabsq $0, %rax; mov %rax, %cr3;"
"_wrapper_mov_cr3: movabsq $0, %r13; mov %r13, %cr3;"
// Find syscall handler
"mov 128(%rsp), %rdx;"
"lea _ZL11syscall_map(%rip), %rax;"
"lea _ZL11syscall_map(%rip), %r13;"
"1:"
"cmp %rdx, (%rax);"
"cmp %rax, (%r13);"
"je 1f;"
"cmpq $0, (%rax);"
"cmpq $0, (%r13);"
"je 2f;"
"add $16, %rax;"
"add $16, %r13;"
"jmp 1b;"
"1: mov 8(%rax), %rax; callq *%rax; jmp 3f;"
"2: ud2;"
"3:"
"1:"
"mov %rcx, %r14; callq *8(%r13); mov %r14, %rcx;"
// Restore process stack & pagetable
"pop %rcx; pop %rax; mov %rcx, %rsp; mov %rax, %cr3;"
"mov %r12, %rsp; mov %rbx, %cr3;"
// Restore registers
"pop %r15;"
......@@ -118,28 +131,18 @@ void __attribute((naked)) Syscall::wrapper() {
"pop %r13;"
"pop %r12;"
"pop %r11;"
"pop %r10;"
"pop %r9;"
"pop %r8;"
"pop %rdi;"
"pop %rsi;"
"pop %rbp;"
"pop %rbx;"
"pop %rdx;"
"pop %rcx;"
"pop %rax;"
// Return to ring3
"sysretq;"
"2: ud2;"
);
}
void Syscall::setup() {
asm volatile(
"mov %%cr3, %%rax; mov %%rax, 2 + _wrapper_mov_cr3(%%rip)":::"%rax"
);
asm volatile("mov %%cr3, %%rax; mov %%rax, 2 + _wrapper_mov_cr3(%%rip)":::"%rax");
wrmsr(MSR_STAR, uint64_t(0x10) << 48 | uint64_t(0x8) << 32);
wrmsr(MSR_LSTAR, uintptr_t(wrapper));
wrmsr(MSR_SFMASK, MSR_SFMASK_IE);
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | MSR_EFER_SCE);
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | MSR_EFER_SCE | MSR_EFER_NXE);
}
......@@ -4,6 +4,7 @@ static const uint32_t MSR_LSTAR = 0xC0000082;
static const uint32_t MSR_SFMASK = 0xC0000084;
static const uint64_t MSR_SFMASK_IE = 1 << 9;
static const uint64_t MSR_EFER_SCE = 1 << 0;
static const uint64_t MSR_EFER_NXE = 1 << 11;
static inline void wrmsr(uint32_t msr_id, uint64_t msr_value) {
asm volatile("wrmsr"::"c"(msr_id), "A"(msr_value), "d"(msr_value >> 32));
......
......@@ -27,9 +27,11 @@ class Process {
List<Thread*> threads;
List<ProcessSymbol> symbols;
uintptr_t entry;
void addPage(uintptr_t vaddr, void* paddr, uint8_t flags);
uintptr_t _aslrCode, _aslrStack;
Pagetable::Entry* addPage(uintptr_t vaddr, void* paddr, uint8_t flags);
uintptr_t _aslrCode, _aslrStack, _syscallPage;
size_t _syscallNum;
void *iomap[2];
char *name;
public:
Process();
......@@ -49,10 +51,13 @@ class Process {
uintptr_t linkLibrary(const char* funcname);
void allowIOPorts(uint16_t min, uint16_t max);
void writeData(uintptr_t address, void* src, size_t size);
void writeData(uintptr_t address, const void* src, size_t size);
void readData(void* dst, uintptr_t address, size_t size) const;
char* readString(uintptr_t address) const;
const char *getName() const;
void setName(const char *name);
void* getPhysicalAddress(uintptr_t ptr) const PURE;
static void print_stacktrace(uintptr_t base = 0, const Process *process = nullptr);
......
......@@ -104,6 +104,7 @@ bool ModuleManager::bindRequirement(const char *req, Process *process) {
}
bool ModuleManager::bindRequirements(const char *reqs, Process *process) {
if (reqs == nullptr) return 1;
const char *re;
char *r;
while (*reqs != 0) {
......@@ -136,6 +137,7 @@ void ModuleManager::loadStream(Stream *stream) {
delete process;
break;
}
process->setName(mod.name);
if (bindRequirements(mod.requirements, process)) {
process->startup();
} else {
......@@ -150,8 +152,7 @@ void ModuleManager::loadStream(Stream *stream) {
sub->seek(ptrdiff_t(size), -1);
if (!stream->eof()) {
Stream *_sub = sub->substream();
if (sub != stream)
delete sub;
if (sub != stream) delete sub;
sub = _sub;
}
}
......
......@@ -5,16 +5,20 @@
#include "processmanager.hpp"
#include "syscall.hpp"
#include "acpi.hpp"
using PTE = Pagetable::Entry;
Process::Process() {
id = size_t(-1);
pagetable = nullptr;
entry = 0;
_aslrCode = RAND::get<uintptr_t>(0x80000000llu, 0x100000000llu) << 12;
_aslrStack = RAND::get<uintptr_t>(0x40000000llu, 0x80000000llu) << 12;
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),
name(nullptr),
pagetable(nullptr) {
iomap[0] = iomap[1] = nullptr;
}
Process::~Process() {
void *rsp; asm volatile("mov %%rsp, %q0; and $~0xFFF, %q0":"=r"(rsp));
if (pagetable != nullptr) {
......@@ -61,9 +65,10 @@ Process::~Process() {
ProcessManager::getManager()->dequeueThread(threads[i]);
delete threads[i];
}
delete name;
}
void Process::addPage(uintptr_t vaddr, void* paddr, uint8_t flags) {
PTE* Process::addPage(uintptr_t vaddr, void* paddr, uint8_t flags) {
uint16_t ptx = (vaddr >> (12 + 9 + 9 + 9)) & 0x1FF;
uint16_t pdx = (vaddr >> (12 + 9 + 9)) & 0x1FF;
uint16_t pdpx = (vaddr >> (12 + 9)) & 0x1FF;
......@@ -92,6 +97,7 @@ void Process::addPage(uintptr_t vaddr, void* paddr, uint8_t flags) {
PTE *pml4e = pte.getPTE();
flags |= 1;
pml4e[pml4x] = PTE(paddr, flags);
return &pml4e[pml4x];
}
uintptr_t Process::addSection(SectionType type, size_t size) {
......@@ -124,7 +130,7 @@ uintptr_t Process::addSection(SectionType type, size_t size) {
flags |= 2;
break;
}
addPage(vaddr, Pagetable::alloc(), flags);
addPage(vaddr, Pagetable::alloc(), flags)->nx = type != SectionTypeCode;
vaddr += 0x1000;
}
return addr;
......@@ -142,38 +148,44 @@ uintptr_t Process::getSymbolByName(const char* name) {
}
return 0;
}
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;
uintptr_t Process::linkLibrary(const char* funcname) {
if (klib::strcmp(funcname, "kptr_acpi_rsdp") == 0) {
return uintptr_t(ACPI::getController()->getRSDPAddr());
}
uintptr_t ptr = getSymbolByName(funcname);
if (ptr != 0) return ptr;
uint64_t syscall_id;
if ((syscall_id = Syscall::callByName(funcname)) != 0) {
struct {
uint8_t sbp[4];
uint8_t pushac11[4];
uint8_t movabs[2];
uint64_t syscall_id;
uint8_t syscall[2];
uint8_t popac11b[5];
uint8_t ret;
} PACKED call = {
{ 0x55, 0x48, 0x89, 0xe5 },
{ 0x50, 0x51, 0x41, 0x53 },
{ 0x48, 0xb8 },
syscall_id,
{ 0x0f, 0x05 },
{ 0x41, 0x5b, 0x59, 0x58, 0x5d },
0xc3
};
ptr = addSection(SectionTypeCode, sizeof(call));
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);
writeData(ptr, &call, sizeof(call));
addSymbol(funcname, ptr);
}
return ptr;
}
void Process::writeData(uintptr_t address, void* src, size_t size) {
char *ptr = static_cast<char*>(src);
void Process::writeData(uintptr_t address, const void* src, size_t size) {
const uint8_t *ptr = static_cast<const uint8_t*>(src);
while (size > 0) {
void *dest = getPhysicalAddress(address);
size_t limit = 0x1000 - (uintptr_t(dest) & 0xFFF);
......@@ -276,7 +288,9 @@ void Process::startup() {
handler &= KB4;
sc_wrapper &= KB4;
addPage(handler, reinterpret_cast<void*>(handler), 1);
addPage(handler + 0x1000, reinterpret_cast<void*>(handler + 0x1000), 1);
addPage(sc_wrapper, reinterpret_cast<void*>(sc_wrapper), 1);
addPage(sc_wrapper + 0x1000, reinterpret_cast<void*>(sc_wrapper + 0x1000), 1);
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);
......@@ -320,13 +334,19 @@ void Process::startup() {
}
void Process::exit(int code) {
printf("EXIT %d\n", code);
(void)code; // TODO: handle
for (size_t i = 0; i < threads.getCount(); i++) {
ProcessManager::getManager()->dequeueThread(threads[i]);
}
delete this;
}
const char *Process::getName() const { return name; }
void Process::setName(const char *newname) {
delete name;
name = newname ? klib::strdup(newname) : nullptr;
}
void Process::print_stacktrace(uintptr_t base, const Process *process) {
struct stackframe {
struct stackframe* rbp;
......
......@@ -108,7 +108,7 @@ uint64_t ProcessManager::RegisterProcess(Process *process) {
Mutex::CriticalLock lock(processSwitchMutex);
uint64_t pid = 1;
for (size_t i = 0; i < processes.getCount(); i++) {
pid = klib::max(pid, processes[i]->getId());
pid = klib::max(pid, processes[i]->getId() + 1);
}
processes.add(process);
return pid;
......
This diff is collapsed.
static const uint32_t ELF_MAGIC = 0x464C457F; // '\x7fELF'
enum ELF_CLASS: uint8_t {
EC_NONE = 0,
EC_32 = 1,
EC_64 = 2
};
enum ELF_DATA: uint8_t {
ED_NONE = 0,
ED_2LSB = 1,
ED_2MSB = 2
};
enum ELF_FILE_VERSION: uint8_t {
EVF_NONE = 0,
EVF_CURRENT = 1
};
enum ELF_OSABI: uint8_t { };
enum ELF_ABIVERSION: uint8_t { };
struct ELF_IDENT {
uint32_t magic;
ELF_CLASS eclass;
ELF_DATA data;
ELF_FILE_VERSION version;
ELF_OSABI osabi;
ELF_ABIVERSION abiversion;
uint8_t pad[7];
} PACKED;
enum ELF_TYPE: uint16_t {
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4
};
enum ELF_MACHINE: uint16_t {
EM_NONE = 0,
EM_386 = 3,
EM_AMD64 = 62
};
enum ELF_VERSION: uint32_t {
EV_NONE = 0,
EV_CURRENT = 1
};
struct ELF_HDR {
ELF_IDENT ident;
ELF_TYPE type;
ELF_MACHINE machine;
ELF_VERSION version;
uint64_t entry, phoff, shoff;
uint32_t flags;
uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstrndx;
} PACKED;
enum ELF64_PROG_TYPE: uint32_t {
PT_NULL,
PT_LOAD,
PT_DYNAMIC,
PT_INTERP,
PT_NOTE,
PT_SHLIB,
PT_PHDR,
PT_TLS,
PT_LOOS = 0x60000000,
PT_HIOS = 0x6FFFFFFF,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7FFFFFFF
};
enum ELF64_PROG_FLAGS: uint32_t {
PF_X = 1,
PF_W = 2,
PF_R = 4
};
struct ELF64_PROG {
ELF64_PROG_TYPE type;
ELF64_PROG_FLAGS flags;
uint64_t offset;
uint64_t vaddr;
uint64_t paddr;
uint64_t filesz;
uint64_t memsz;
uint64_t align;
} PACKED;
enum ELF64_SECT_TYPE: uint32_t {
SHT_NULL,
SHT_PROGBITS,
SHT_SYMTAB,
SHT_STRTAB,
SHT_RELA,
SHT_HASH,
SHT_DYNAMIC,
SHT_NOTE,
SHT_NOBITS,
SHT_REL,
SHT_SHLIB,
SHT_DYNSYM
};
enum ELF64_SECT_FLAGS: uint64_t {
SHF_WRITE = 1,
SHF_ALLOC = 2,
SHF_EXECINSTR = 4
};
struct ELF64_SECT {
uint32_t name;
ELF64_SECT_TYPE type;
ELF64_SECT_FLAGS flags;
uint64_t addr, offset, size;
uint32_t link, info;
uint64_t addralign, entsize;
} PACKED;
enum ELF64_DYN_TAG: uint64_t {
DT_NULL,
DT_NEEDED,
DT_PLTRELSZ,
DT_PLTGOT,
DT_HASH,
DT_STRTAB,
DT_SYMTAB,
DT_RELA,
DT_RELASZ,
DT_RELAENT,
DT_STRSZ,
DT_SYMENT,
DT_INIT,
DT_FINI,
DT_SONAME,
DT_RPATH,
DT_SYMBOLIC,
DT_REL,
DT_RELSZ,
DT_RELENT,
DT_PLTREL,
DT_DEBUG,
DT_TEXTREL,
DT_JMPREL,
DT_BIND_NOW,
DT_INIT_ARRAY,
DT_FINI_ARRAY,
DT_INIT_ARRAYSZ,
DT_FINI_ARRAYSZ,
DT_RUNPATH,
DT_FLAGS,
DT_ENCODING,
DT_PREINIT_ARRAY,
DT_PREINIT_ARRAYSZ,
DT_MAXPOSTAGS,
DT_LOOS = 0x60000000,
DT_GNU_HASH = 0x6FFFFEF5,
DT_HIOS = 0x6FFFFFFF,
DT_LOPROC = 0x70000000,
DT_HIPROC = 0x7FFFFFFF
};
enum ELF64_RELOC_TYPE: uint32_t {
R_X86_64_NONE, // No reloc
R_X86_64_64, // Direct 64 bit
R_X86_64_PC32, // PC relative 32 bit signed
R_X86_64_GOT32, // 32 bit GOT entry
R_X86_64_PLT32, // 32 bit PLT address
R_X86_64_COPY, // Copy symbol at runtime
R_X86_64_GLOB_DAT, // Create GOT entry
R_X86_64_JUMP_SLOT, // Create PLT entry
R_X86_64_RELATIVE, // Adjust by program base
R_X86_64_GOTPCREL, // 32 bit signed pc relative offset to GOT
R_X86_64_32, // Direct 32 bit zero extended
R_X86_64_32S, // Direct 32 bit sign extended
R_X86_64_16, // Direct 16 bit zero extended
R_X86_64_PC16, // 16 bit sign extended pc relative
R_X86_64_8, // Direct 8 bit sign extended
R_X86_64_PC8 // 8 bit sign extended pc relative
};
struct ELF64_DYN {
ELF64_DYN_TAG tag;
uint64_t val;
} PACKED;
struct ELF64SYM {
uint32_t name;
uint8_t info, other;
uint16_t shndx;
uint64_t value;
uint64_t size;
} PACKED;
struct ELF64RELA {
uint64_t addr;
ELF64_RELOC_TYPE type;
uint32_t sym;
uint64_t add;
} PACKED;
struct ELF64REL {
uint64_t addr;
ELF64_RELOC_TYPE type;
uint32_t sym;
} PACKED;
namespace ELF {
enum CLASS: uint8_t {
EC_NONE = 0,
EC_32 = 1,
EC_64 = 2
};
enum DATA: uint8_t {
ED_NONE = 0,
ED_2LSB = 1,
ED_2MSB = 2
};
enum FILE_VERSION: uint8_t {
EVF_NONE = 0,
EVF_CURRENT = 1
};
enum OSABI: uint8_t { };
enum ABIVERSION: uint8_t { };
enum TYPE: uint16_t {
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4
};
enum MACHINE: uint16_t {
EM_NONE = 0,
EM_386 = 3,
EM_AMD64 = 62
};
enum VERSION: uint32_t {
EV_NONE = 0,
EV_CURRENT = 1
};
struct IDENT {
static const uint32_t MAGIC = 0x464C457F; // '\x7fELF'
uint32_t magic;
CLASS eclass;
DATA data;
FILE_VERSION version;
OSABI osabi;
ABIVERSION abiversion;
uint8_t pad[7];
} PACKED;
struct HDR {
IDENT ident;
TYPE type;
MACHINE machine;
VERSION version;
uint64_t entry, phoff, shoff;
uint32_t flags;
uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstrndx;
} PACKED;
namespace _64 {
struct PROG {
enum TYPE: uint32_t {
PT_NULL,
PT_LOAD,
PT_DYNAMIC,
PT_INTERP,
PT_NOTE,
PT_SHLIB,
PT_PHDR,
PT_TLS,
PT_LOOS = 0x60000000,
PT_HIOS = 0x6FFFFFFF,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7FFFFFFF
};
enum FLAGS: uint32_t {
PF_X = 1,
PF_W = 2,
PF_R = 4
};
TYPE type;
FLAGS flags;
uint64_t offset;
uint64_t vaddr;
uint64_t paddr;
uint64_t filesz;
uint64_t memsz;
uint64_t align;
} PACKED;
struct SECT {
enum TYPE: uint32_t {
SHT_NULL,
SHT_PROGBITS,
SHT_SYMTAB,
SHT_STRTAB,
SHT_RELA,
SHT_HASH,
SHT_DYNAMIC,
SHT_NOTE,
SHT_NOBITS,
SHT_REL,
SHT_SHLIB,
SHT_DYNSYM
};
enum FLAGS: uint64_t {
SHF_WRITE = 1,
SHF_ALLOC = 2,
SHF_EXECINSTR = 4
};
uint32_t name;
TYPE type;
FLAGS flags;
uint64_t addr, offset, size;
uint32_t link, info;
uint64_t addralign, entsize;
} PACKED;
struct DYN {
enum TAG: uint64_t {
DT_NULL,
DT_NEEDED,
DT_PLTRELSZ,
DT_PLTGOT,
DT_HASH,
DT_STRTAB,
DT_SYMTAB,
DT_RELA,
DT_RELASZ,
DT_RELAENT,
DT_STRSZ,
DT_SYMENT,
DT_INIT,
DT_FINI,
DT_SONAME,
DT_RPATH,
DT_SYMBOLIC,
DT_REL,
DT_RELSZ,
DT_RELENT,
DT_PLTREL,
DT_DEBUG,
DT_TEXTREL,
DT_JMPREL,
DT_BIND_NOW,
DT_INIT_ARRAY,
DT_FINI_ARRAY,
DT_INIT_ARRAYSZ,
DT_FINI_ARRAYSZ,
DT_RUNPATH,
DT_FLAGS,
DT_ENCODING,
DT_PREINIT_ARRAY,
DT_PREINIT_ARRAYSZ,
DT_MAXPOSTAGS,
DT_LOOS = 0x60000000,
DT_GNU_HASH = 0x6FFFFEF5,
DT_HIOS = 0x6FFFFFFF,
DT_LOPROC = 0x70000000,
DT_HIPROC = 0x7FFFFFFF
};
TAG tag;
uint64_t val;
} PACKED;
struct SYM {
enum BIND: uint8_t {
STB_LOCAL = 0,
STB_GLOBAL = 1,
STB_WEAK = 2,
STB_LOOS = 10,
STB_HIOS = 12,
STB_LOPROC = 13,
STB_HIPROC = 15,
};
enum TYPE: uint8_t {
STT_NOTYPE = 0,
STT_OBJECT = 1,
STT_FUNC = 2,
STT_SECTION = 3,
STT_FILE = 4,
STT_COMMON = 5,
STT_TLS = 6,
STT_LOOS = 10,
STT_HIOS = 12,
STT_LOPROC = 13,
STT_SPARC_REGISTER = 13,
STT_HIPROC = 15,
};
uint32_t name;
BIND bind:4; TYPE type:4;
uint8_t other;
uint16_t shndx;
uint64_t value;
uint64_t size;
} PACKED;
enum RELOC_TYPE: uint32_t {
R_X86_64_NONE, // No reloc
R_X86_64_64, // Direct 64 bit
R_X86_64_PC32, // PC relative 32 bit signed
R_X86_64_GOT32, // 32 bit GOT entry
R_X86_64_PLT32, // 32 bit PLT address
R_X86_64_COPY, // Copy symbol at runtime
R_X86_64_GLOB_DAT, // Create GOT entry
R_X86_64_JUMP_SLOT, // Create PLT entry
R_X86_64_RELATIVE, // Adjust by program base
R_X86_64_GOTPCREL, // 32 bit signed pc relative offset to GOT
R_X86_64_32, // Direct 32 bit zero extended
R_X86_64_32S, // Direct 32 bit sign extended
R_X86_64_16, // Direct 16 bit zero extended
R_X86_64_PC16, // 16 bit sign extended pc relative
R_X86_64_8, // Direct 8 bit sign extended
R_X86_64_PC8 // 8 bit sign extended pc relative
};
struct REL {
uint64_t addr;
RELOC_TYPE type;
uint32_t sym;
} PACKED;
struct RELA : public REL {
uint64_t add;
} PACKED;
}
}
namespace ELF64 = ELF::_64;