...
 
Commits (5)
......@@ -10,6 +10,7 @@ class List {
Item *items = nullptr;
size_t count = 0;
size_t capacity = 0;
public:
~List() { Heap::free(items); }
......@@ -26,7 +27,8 @@ class List {
void add(const Item &item) { insert() = item; }
size_t getCount() { return count; }
size_t getCount() const { return count; }
Item& operator[] (const size_t index) { return items[index]; }
const Item& operator[] (const size_t index) const { return items[index]; }
};
......@@ -10,6 +10,60 @@
Mutex ACPI::controllerMutex;
volatile ACPI* ACPI::controller = nullptr;
enum LAPIC_VALUES {
LAPIC_DISABLE = 0x10000,
LAPIC_SW_ENABLE = 0x100,
LAPIC_CPUFOCUS = 0x200,
LAPIC_NMI = (4 << 8),
TMR_PERIODIC = 0x20000,
TMR_BASEDIV = (1 << 20),
};
enum IOAPIC_FIELDS {
IOAPIC_REGSEL = 0x0, IOAPIC_REGWIN = 0x10,
};
enum IOAPIC_REGS {
IOAPIC_ID = 0x0, IOAPIC_VER = 0x1, IOAPIC_REDTBL = 0x10,
};
struct ACPI::Header {
uint32_t signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oem[6];
uint8_t oemTableId[8];
uint32_t oemRevision;
uint32_t creatorId;
uint32_t creatorRevision;
};
struct ACPI::Madt : Header {
uint32_t localApicAddr;
uint32_t flags;
};
struct ACPI::ApicHeader {
uint8_t type;
uint8_t length;
};
struct ACPI::ApicLocalApic : ApicHeader {
uint8_t acpiProcessorId;
uint8_t apicId;
uint32_t flags;
};
struct ACPI::ApicIoApic : ApicHeader {
uint8_t ioApicId;
uint8_t reserved;
uint32_t ioApicAddress;
uint32_t globalSystemInterruptBase;
};
struct ACPI::ApicInterruptOverride : ApicHeader {
uint8_t bus;
uint8_t source;
uint32_t interrupt;
uint16_t flags;
};
ACPI* ACPI::getController() {
if (controller) return const_cast<ACPI*>(controller);
Mutex::CriticalLock lock(controllerMutex);
......@@ -17,6 +71,15 @@ ACPI* ACPI::getController() {
return const_cast<ACPI*>(controller);
}
inline static void MmioWrite32(void *p, uint32_t data) {
Pagetable::map(p);
*reinterpret_cast<volatile uint32_t *>(p) = data;
}
inline static uint32_t MmioRead32(const void *p) {
Pagetable::map(p);
return *reinterpret_cast<const volatile uint32_t *>(p);
}
ACPI::ACPI() {
static const void *const ACPI_FIND_START = reinterpret_cast<const void*>(0x000e0000);
static const void *const ACPI_FIND_TOP = reinterpret_cast<const void*>(0x000fffff);
......@@ -123,7 +186,7 @@ void ACPI::ParseApic(const Madt *madt) {
Pagetable::map(localApicAddr);
const uint8_t *p = reinterpret_cast<const uint8_t*>(madt + 1);
const uint8_t *end = p + (madt->header.length - sizeof(Madt));
const uint8_t *end = p + (madt->Header::length - sizeof(Madt));
while (p < end) {
const ApicHeader *header = reinterpret_cast<const ApicHeader*>(p);
......@@ -132,15 +195,14 @@ void ACPI::ParseApic(const Madt *madt) {
uint16_t type = header->type;
uint16_t length = header->length;
if (type == 0) {
const ApicLocalApic *s = reinterpret_cast<const ApicLocalApic*>(p);
const ApicLocalApic *s = reinterpret_cast<const ApicLocalApic*>(header);
acpiCpuIds[acpiCpuCount++] = s->apicId;
} else if (type == 1) {
const ApicIoApic *s = reinterpret_cast<const ApicIoApic*>(p);
const ApicIoApic *s = reinterpret_cast<const ApicIoApic*>(header);
ioApicAddr = reinterpret_cast<char*>(uintptr_t(s->ioApicAddress));
Pagetable::map(ioApicAddr);
} else if (type == 2) {
const ApicInterruptOverride *s =
reinterpret_cast<const ApicInterruptOverride*>(p);
const ApicInterruptOverride *s = reinterpret_cast<const ApicInterruptOverride*>(header);
(void)s;
// TODO: handle interrupt overrides
}
......
......@@ -183,9 +183,6 @@ void* operator new(size_t a) {
void* operator new[](size_t a) {
return Heap::alloc(a);
}
void* operator new(size_t, size_t a) {
return Heap::alloc(a);
}
void operator delete(void* a) noexcept {
return Heap::free(a);
}
......
......@@ -27,66 +27,6 @@ class ACPI {
LAPIC_TMRDIV = 0x3E0,
LAPIC_LAST = 0x38F,
};
private:
enum LAPIC_VALUES {
LAPIC_DISABLE = 0x10000,
LAPIC_SW_ENABLE = 0x100,
LAPIC_CPUFOCUS = 0x200,
LAPIC_NMI = (4 << 8),
TMR_PERIODIC = 0x20000,
TMR_BASEDIV = (1 << 20),
};
enum IOAPIC_FIELDS {
IOAPIC_REGSEL = 0x0, IOAPIC_REGWIN = 0x10,
};
enum IOAPIC_REGS {
IOAPIC_ID = 0x0, IOAPIC_VER = 0x1, IOAPIC_REDTBL = 0x10,
};
struct Header {
uint32_t signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oem[6];
uint8_t oemTableId[8];
uint32_t oemRevision;
uint32_t creatorId;
uint32_t creatorRevision;
};
struct Madt {
Header header;
uint32_t localApicAddr;
uint32_t flags;
};
struct ApicHeader {
uint8_t type;
uint8_t length;
};
struct ApicLocalApic {
ApicHeader header;
uint8_t acpiProcessorId;
uint8_t apicId;
uint32_t flags;
};
struct ApicIoApic {
ApicHeader header;
uint8_t ioApicId;
uint8_t reserved;
uint32_t ioApicAddress;
uint32_t globalSystemInterruptBase;
};
struct ApicInterruptOverride {
ApicHeader header;
uint8_t bus;
uint8_t source;
uint32_t interrupt;
uint16_t flags;
};
union IOApicRedir {
struct {
uint8_t vector :8;
......@@ -104,6 +44,13 @@ class ACPI {
};
private:
struct Header;
struct Madt;
struct ApicHeader;
struct ApicLocalApic;
struct ApicIoApic;
struct ApicInterruptOverride;
static Mutex controllerMutex;
static volatile ACPI *controller;
......
......@@ -21,9 +21,24 @@ class Heap {
static void free(void* addr);
};
#define ALIGNED_NEW(align) \
void *operator new(size_t size) { return Heap::alloc(size, align); }
#define ALIGNED_NEWARR(align) \
void *operator new[](size_t size) { return Heap::alloc(size, align); }
template<typename T> class ptr {
private:
T *value;
public:
ptr() : value(nullptr) {}
explicit ptr(T *value) : value(value) {}
~ptr() { delete value; }
void *operator new(size_t, size_t);
inline void reset(T* newvalue) { delete value; value = newvalue; }
inline void operator=(T* newvalue) { reset(newvalue); }
inline operator bool() const { return value != nullptr; }
inline T& operator*() { return *value; }
inline T* operator->() { return value; }
inline T* get() { return value; }
inline T& operator[](ptrdiff_t idx) { return value[idx]; }
inline const T& operator*() const { return *value; }
inline const T* operator->() const { return value; }
inline const T* get() const { return value; }
inline const T& operator[](ptrdiff_t idx) const { return value[idx]; }
};
......@@ -138,8 +138,6 @@ class Interrupts {
offset_low(uint16_t(offset)), selector(selector), ist(ist), rsvd1(0),
type(type), rsvd2(0), dpl(dpl), present(present),
offset_middle(uint16_t(offset >> 16)), offset_high(offset >> 32), rsvd3(0) {}
ALIGNED_NEWARR(0x1000)
} PACKED;
private:
......
......@@ -76,12 +76,3 @@ class Pagetable {
static void* lowalloc(size_t count = 1);
static void free(void* page);
};
inline static void MmioWrite32(void *p, uint32_t data) {
Pagetable::map(p);
*reinterpret_cast<volatile uint32_t *>(p) = data;
}
inline static uint32_t MmioRead32(const void *p) {
Pagetable::map(p);
return *reinterpret_cast<const volatile uint32_t *>(p);
}
......@@ -10,9 +10,8 @@
static void syscall_puts(uintptr_t strptr) {
Process *process = ProcessManager::getManager()->currentProcess();
const char *str = process->readString(strptr);
Display::getInstance()->write(str);
delete str;
ptr<char> str(process->readString(strptr));
Display::getInstance()->write(str.get());
}
static void syscall_exit(int code) {
......@@ -37,11 +36,10 @@ static void syscall_kread(void *out, const void *kaddr, size_t size) {
process->writeData(uintptr_t(out), kaddr, size);
}
static void syscall_ioprovide(const char *path, const void *ptr) {
static void syscall_ioprovide(const char *path, const void *modptr) {
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;
ptr<char> str(process->readString(uintptr_t(path)));
printf("ioprovide [%s(%#lx) / %p] [%s]\n", process->getName(), process->getId(), modptr, str.get());
}
#define SYSCALL_ENT(name) { \
......
......@@ -9,14 +9,14 @@
class ModuleManager {
private:
struct ModuleInfo {
char *name, *version, *description, *requirements, *developer;
ptr<char> name, version, description, requirements, developer;
};
static Mutex managerMutex;
static volatile ModuleManager* manager;
void parseInternal();
void parseInitRD();
void loadStream(Stream *stream);
bool parseModuleInfo(ModuleInfo *info, Process *process);
bool parseModuleInfo(ModuleInfo *info, const Process *process);
bool bindRequirement(const char *req, Process *process);
bool bindRequirements(const char *reqs, Process *process);
static void init();
......
......@@ -40,14 +40,14 @@ class Process {
void exit(int code);
void addThread(Thread *thread, bool suspended);
uint64_t getId() { return id; }
uint64_t getId() const { return id; }
Pagetable::Entry *pagetable;
uintptr_t addSection(SectionType type, size_t size);
void addSymbol(const char *name, uintptr_t ptr);
void setEntryAddress(uintptr_t ptr);
uintptr_t getSymbolByName(const char* name) PURE;
uintptr_t getSymbolByName(const char* name) const PURE;
uintptr_t linkLibrary(const char* funcname);
void allowIOPorts(uint16_t min, uint16_t max);
......
......@@ -4,9 +4,7 @@
#pragma once
#include "kernlib.hpp"
class Thread {
public:
Thread();
struct Thread {
struct {
uint64_t rip, rflags;
uint64_t rsi, rdi, rbp, rsp;
......@@ -16,4 +14,5 @@ class Thread {
} regs;
uint64_t suspend_ticks;
uint64_t stack_top;
Thread() : regs(), suspend_ticks(0), stack_top(0) {}
};
......@@ -9,32 +9,32 @@
volatile ModuleManager* ModuleManager::manager = nullptr;
Mutex ModuleManager::managerMutex;
bool ModuleManager::parseModuleInfo(ModuleInfo *info, Process *process) {
bool ModuleManager::parseModuleInfo(ModuleInfo *info, const Process *process) {
info->name = nullptr;
info->version = nullptr;
info->description = nullptr;
info->requirements = nullptr;
info->developer = nullptr;
struct {
uintptr_t entry, name, version, desc, reqs, dev;
uintptr_t name, version, desc, reqs, dev;
} symbols = {
process->getSymbolByName("module"),
process->getSymbolByName("module_name"),
process->getSymbolByName("module_version"),
process->getSymbolByName("module_description"),
process->getSymbolByName("module_requirements"),
process->getSymbolByName("module_developer")
};
ModuleInfo mod = { nullptr, nullptr, nullptr, nullptr, nullptr };
if ((symbols.entry == 0) || (symbols.name == 0) || (symbols.version == 0)
if ((symbols.name == 0) || (symbols.version == 0)
|| (symbols.desc == 0) || (symbols.reqs == 0) || (symbols.dev == 0))
return false;
process->setEntryAddress(symbols.entry);
mod.name = process->readString(symbols.name);
mod.version = process->readString(symbols.version);
mod.description = process->readString(symbols.desc);
mod.requirements = process->readString(symbols.reqs);
mod.developer = process->readString(symbols.dev);
*info = mod;
info->name = process->readString(symbols.name);
info->version = process->readString(symbols.version);
info->description = process->readString(symbols.desc);
info->requirements = process->readString(symbols.reqs);
info->developer = process->readString(symbols.dev);
return true;
}
......@@ -130,24 +130,18 @@ void ModuleManager::loadStream(Stream *stream) {
size_t size;
ModuleInfo mod;
for (;;) {
mod = {nullptr, nullptr, nullptr, nullptr, nullptr};
process = new Process();
size = readelf(process, sub);
if (size == 0 || !parseModuleInfo(&mod, process)) {
delete process;
break;
}
process->setName(mod.name);
if (bindRequirements(mod.requirements, process)) {
process->setName(mod.name.get());
if (bindRequirements(mod.requirements.get(), process)) {
process->startup();
} else {
delete process;
}
delete mod.name;
delete mod.version;
delete mod.description;
delete mod.requirements;
delete mod.developer;
sub->seek(ptrdiff_t(size), -1);
if (!stream->eof()) {
......@@ -156,8 +150,7 @@ void ModuleManager::loadStream(Stream *stream) {
sub = _sub;
}
}
if (sub != stream)
delete sub;
if (sub != stream) delete sub;
}
void ModuleManager::parseInternal() {
const char *mods_start, *mods_end;
......
......@@ -137,7 +137,7 @@ void Process::addSymbol(const char *name, uintptr_t ptr) {
void Process::setEntryAddress(uintptr_t ptr) {
entry = ptr;
}
uintptr_t Process::getSymbolByName(const char* name) {
uintptr_t Process::getSymbolByName(const char* name) const {
for (size_t i = 0; i < symbols.getCount(); i++) {
if (klib::strcmp(symbols[i].name, name) == 0)
return symbols[i].ptr;
......
// PhoeniX OS Thread subsystem
// Copyright © 2017 Yury Popov a.k.a. PhoeniX
#include "thread.hpp"
Thread::Thread() {
regs = {
0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
suspend_ticks = 0;
stack_top = 0;
}
......@@ -106,19 +106,17 @@ static bool readelf_dylink_process_reloc(Process *process, uintptr_t start, cons
if (!sym.name) return 0;
uintptr_t addr = 0;
char *name = process->readString(strtab + sym.name);
ptr<char> name(process->readString(strtab + sym.name));
uintptr_t ptr = readelf_find_load_addr(process, start, ent.addr);
bool allownull = sym.bind == ELF64::SYM::STB_WEAK;
addr = process->getSymbolByName(name);
if (!addr) addr = process->linkLibrary(name);
addr = process->getSymbolByName(name.get());
if (!addr) addr = process->linkLibrary(name.get());
if (!allownull && addr == 0) {
printf("Cannot link symbol: %s\n", name);
delete name;
printf("Cannot link symbol: %s\n", name.get());
return 0;
}
delete name;
addr += ent.add;
switch (ent.type) {
......@@ -209,6 +207,7 @@ static bool readelf_dylink_handle_dynamic_symtab(Process *process, uintptr_t sta
} PACKED hashhdr;
process->readData(&hashhdr, hashtab, sizeof(hashhdr));
hashtab += sizeof(hashhdr);
ptr<char> name;
for (uint32_t si = 0; si < hashhdr.nbucket + hashhdr.nchain; si++) {
uint32_t idx;
process->readData(&idx, hashtab, sizeof(idx));
......@@ -218,9 +217,8 @@ static bool readelf_dylink_handle_dynamic_symtab(Process *process, uintptr_t sta
if (sym.name == 0) continue;
uintptr_t ptr = readelf_find_load_addr(process, start, sym.value);
if (ptr == 0) continue;
char *name = process->readString(strtab + sym.name);
if (name && name[0] != 0) process->addSymbol(name, ptr);
delete name;
name = process->readString(strtab + sym.name);
if (name && name[0] != 0) process->addSymbol(name.get(), ptr);
}
return 1;
}
......@@ -296,14 +294,15 @@ static bool readelf_dylink(Process *process, uintptr_t start) {
size_t readelf(Process *process, Stream *stream) {
ELF::HDR elf;
size_t size = 0;
ELF64::PROG *progs = nullptr, *progs_top, *prog;
char *buf = nullptr;
ELF64::PROG *progs_top, *prog;
ptr<ELF64::PROG> progs;
ptr<char> buf;
SectionType type;
uintptr_t vaddr, offset_load, vaddr_start = 0;
// Read ELF header
size_t off = 0;
if (stream->read(&elf, sizeof(ELF::HDR)) != sizeof(ELF::HDR)) goto err;
if (stream->read(&elf, sizeof(ELF::HDR)) != sizeof(ELF::HDR)) return 0;
off += sizeof(ELF::HDR);
// Identify ELF
......@@ -312,35 +311,33 @@ size_t readelf(Process *process, Stream *stream) {
|| (elf.ident.data != ELF::ED_2LSB)
|| (elf.ident.version != ELF::EVF_CURRENT)
|| (elf.ident.osabi != 0)
|| (elf.ident.abiversion != 0)) goto err;
|| (elf.ident.abiversion != 0)) return 0;
// Check ELF type
if ((elf.machine != ELF::EM_AMD64)
|| (elf.type != ELF::ET_DYN)
|| (elf.version != ELF::EV_CURRENT)
|| (elf.flags != 0)
|| (elf.ehsize != sizeof(ELF::HDR))
|| (elf.phoff != sizeof(ELF::HDR))) goto err;
|| (elf.phoff != sizeof(ELF::HDR))) return 0;
// Init variables
size = elf.shoff + elf.shentsize * elf.shnum;
progs = new ELF64::PROG[elf.phnum]();
progs_top = progs + elf.phnum;
progs_top = progs.get() + elf.phnum;
// Read linker program
if (stream->read(progs, sizeof(ELF64::PROG) * elf.phnum) != sizeof(ELF64::PROG) * elf.phnum)
goto err;
if (stream->read(progs.get(), sizeof(ELF64::PROG) * elf.phnum) != sizeof(ELF64::PROG) * elf.phnum) return 0;
off += sizeof(ELF64::PROG) * elf.phnum;
for (prog = progs; prog < progs_top; prog++) {
for (prog = progs.get(); prog < progs_top; prog++) {
switch (prog->type) {
case ELF64::PROG::PT_NULL: break;
case ELF64::PROG::PT_PHDR:
if ((prog->offset != elf.phoff) || (prog->filesz != sizeof(ELF64::PROG) * elf.phnum))
goto err;
if ((prog->offset != elf.phoff) || (prog->filesz != sizeof(ELF64::PROG) * elf.phnum)) return 0;
break;
case ELF64::PROG::PT_LOAD:
if (prog->flags & ELF64::PROG::PF_X) {
if (prog->flags & ELF64::PROG::PF_W) goto err;
if (prog->flags & ELF64::PROG::PF_W) return 0;
type = SectionTypeCode;
} else {
if (prog->flags & ELF64::PROG::PF_W)
......@@ -356,16 +353,15 @@ size_t readelf(Process *process, Stream *stream) {
process->writeData(vaddr, &elf, sizeof(ELF::HDR));
offset_load = sizeof(ELF::HDR) + sizeof(ELF64::PROG) * elf.phnum;
}
if (prog->offset + offset_load < off) goto err;
if (prog->offset + offset_load < off) return 0;
if (prog->offset + offset_load > off) {
stream->seek(ptrdiff_t(prog->offset + offset_load - off), 0);
off = prog->offset + offset_load;
}
buf = new char[prog->filesz - offset_load]();
if (stream->read(buf, prog->filesz - offset_load) != prog->filesz - offset_load) goto err;
if (stream->read(buf.get(), prog->filesz - offset_load) != prog->filesz - offset_load) return 0;
off += prog->filesz - offset_load;
process->writeData(vaddr + offset_load, buf, prog->filesz - offset_load);
delete[] buf; buf = nullptr;
process->writeData(vaddr + offset_load, buf.get(), prog->filesz - offset_load);
prog->vaddr = vaddr;
}
break;
......@@ -373,20 +369,12 @@ size_t readelf(Process *process, Stream *stream) {
default:
if (prog->type >= ELF64::PROG::PT_LOOS && prog->type <= ELF64::PROG::PT_HIOS) break;
if (prog->type >= ELF64::PROG::PT_LOPROC && prog->type <= ELF64::PROG::PT_HIPROC) break;
goto err;
return 0;
}
}
process->writeData(vaddr_start + sizeof(ELF::HDR), progs, sizeof(ELF64::PROG) * elf.phnum);
process->writeData(vaddr_start + sizeof(ELF::HDR), progs.get(), sizeof(ELF64::PROG) * elf.phnum);
goto done;
err:
size = 0;
done:
delete progs;
delete buf;
if (size != 0) {
if (!readelf_dylink(process, vaddr_start)) size = 0;
}
if (!readelf_dylink(process, vaddr_start)) return 0;
return size;
}