...
 
Commits (11)
......@@ -5,7 +5,7 @@ add_custom_target(${EFIROOT}
DEPENDS pxkrnl
)
set(QEMU_FLAGS -smp cores=2,threads=2 -cpu Broadwell -serial stdio)
set(QEMU_FLAGS -smp cores=2,threads=2 -cpu Nehalem-IBRS -serial stdio)
add_custom_target(launch
${QEMU} ${QEMU_FLAGS} -kernel pxkrnl
DEPENDS pxkrnl
......
......@@ -20,7 +20,7 @@ SECTIONS
.reloc 0x400FE0 (NOLOAD) : ALIGN(1) {
LONG(0) LONG(10) SHORT(0)
} :text
.text 0x401000 : ALIGN(1) {
.text 0x401000 : ALIGN(0x1000) {
__text_start__ = . ;
*boot.a:bootstrap.o(.text .text.*)
*(.text .text.*)
......@@ -29,7 +29,7 @@ SECTIONS
. = ALIGN(64);
__text_end__ = . ;
} :text
.rodata : ALIGN(1) {
.rodata : ALIGN(0x1000) {
. = ALIGN(8);
*(.modules)
......@@ -37,7 +37,7 @@ SECTIONS
__data_start__ = . ;
*(.rodata .rodata.*)
} :rodata
.data : ALIGN(1) {
.data : ALIGN(0x1000) {
. = ALIGN(8);
__VTABLE_START__ = . ;
__CTOR_LIST__ = . ; QUAD(0) *(.init_array*) *(.ctor*) QUAD(0)
......@@ -49,7 +49,7 @@ SECTIONS
*(.data .data.*)
__data_end__ = . ;
} :data
.bss (NOLOAD) : ALIGN(1) {
.bss (NOLOAD) : ALIGN(0x1000) {
__bss_start__ = . ;
*(.bss .bss.*)
*(COMMON)
......
......@@ -12,8 +12,8 @@ _start:
.align 4
multiboot_header:
.long 0x1BADB002
.long 0x00010003
.long -(0x1BADB002+0x00010003)
.long 0x00010005
.long -(0x1BADB002+0x00010005)
.long multiboot_header
.long __text_start__
......@@ -21,6 +21,7 @@ multiboot_header:
.long __bss_end__ + 0x80000
.long multiboot_entry
.long 0, 800, 600, 8
multiboot_entry:
cli
......@@ -217,7 +218,6 @@ x64_entry:
call _ZN3SMP4initEv
call _ZN13ModuleManager4initEv
call _ZN7Syscall5setupEv
mov %rsp, %rbp
jmp _ZN14ProcessManager12process_loopEv
reloc_vtables:
......
......@@ -9,14 +9,14 @@ namespace EFI {
const void *ImageHandle = nullptr;
const void *acpi1 = nullptr, *acpi2 = nullptr;
void load();
Framebuffer fb, *fbPtr = nullptr;
Framebuffer fb;
}
const struct EFI::SystemTable *EFI::getSystemTable() { load(); return SystemTable; }
const void *EFI::getImageHandle() { return ImageHandle; }
const void *EFI::getACPI1Addr() { return acpi1; }
const void *EFI::getACPI2Addr() { return acpi2; }
const struct EFI::Framebuffer *EFI::getFramebuffer() { return fbPtr; }
const struct EFI::Framebuffer *EFI::getFramebuffer() { return fb.base ? &fb : nullptr; }
void EFI::load() {
static bool loaded = false;
......@@ -38,7 +38,6 @@ void EFI::load() {
fb.width = graphics_output->Mode->Info->HorizontalResolution;
fb.height = graphics_output->Mode->Info->VerticalResolution;
fb.pixelFormat = graphics_output->Mode->Info->PixelFormat;
fbPtr = &fb;
}
loaded = true;
}
......@@ -204,8 +204,8 @@ namespace EFI {
Status EFIAPI(*const GetMemoryMap)(
uint64_t *MemoryMapSize, MemoryDescriptor *MemoryMap, uint64_t *MapKey, uint64_t *DescriptorSize,
uint32_t *DescriptorVersion);
const void *AllocatePool;
const void *FreePool;
Status EFIAPI(*const AllocatePool)(MemoryType MemoryType, uint64_t size, void **Address);
Status EFIAPI(*const FreePool)(void *Address);
const void *CreateEvent;
const void *SetTimer;
const void *WaitForEvent;
......
......@@ -7,42 +7,133 @@
class Multiboot {
public:
enum Flags: uint32_t {
MB_FLAG_MEM = (1 << 0),
MB_FLAG_BOOTDEV = (1 << 1),
MB_FLAG_CMDLINE = (1 << 2),
MB_FLAG_MODS = (1 << 3),
MB_FLAG_SYMTAB = (1 << 4),
MB_FLAG_ELFSYMTAB = (1 << 5),
MB_FLAG_MEMMAP = (1 << 6),
MB_FLAG_DRIVEMAP = (1 << 7),
MB_FLAG_CONFTAB = (1 << 8),
MB_FLAG_BLNAME = (1 << 9),
MB_FLAG_APMTAB = (1 << 10),
MB_FLAG_VBETAB = (1 << 11)
FLAG_MEM = (1 << 0),
FLAG_BOOTDEV = (1 << 1),
FLAG_CMDLINE = (1 << 2),
FLAG_MODS = (1 << 3),
FLAG_SYMTAB = (1 << 4),
FLAG_ELFSYMTAB = (1 << 5),
FLAG_MEMMAP = (1 << 6),
FLAG_DRIVEMAP = (1 << 7),
FLAG_CONFTAB = (1 << 8),
FLAG_BLNAME = (1 << 9),
FLAG_APMTAB = (1 << 10),
FLAG_VBETAB = (1 << 11),
FLAG_FBTAB = (1 << 12),
};
enum MemoryType: uint32_t {
MEMORY_AVAILABLE = 1,
MEMORY_RESERVED = 2,
MEMORY_ACPI_RECLAIMABLE = 3,
MEMORY_NVS = 4,
MEMORY_BADRAM = 5,
};
enum FramebufferType: uint8_t {
FRAMEBUFFER_TYPE_INDEXED = 0,
FRAMEBUFFER_TYPE_RGB = 1,
FRAMEBUFFER_TYPE_EGA_TEXT = 2,
};
struct Payload {
Flags flags;
size_t mem_lower:32, mem_upper:32;
struct {
size_t lower:32, upper:32;
} PACKED mem;
uint32_t boot_device;
uint32_t pcmdline;
uint32_t mods_count;
uint32_t pmods_addr;
uint32_t syms[3];
uint32_t mmap_length;
uint32_t pmmap_addr;
uint32_t drives_length;
uint32_t pdrives_addr;
uint32_t pconfig_table;
uint32_t pboot_loader_name;
uint32_t papm_table;
uint64_t pvbe_control_info, pvbe_mode_info, pvbe_mode, pvbe_interface_seg,
pvbe_interface_off, pvbe_interface_len;
uintptr_t pcmdline:32;
struct { uint32_t count; uintptr_t paddr:32; } PACKED mods;
union {
struct { uint32_t tabsize, strsize, addr, rsvd; } PACKED aout;
struct { uint32_t num, size, addr, shndx; } PACKED elf;
} PACKED syms;
struct { size_t size:32; uintptr_t paddr:32; } PACKED mmap;
struct { size_t size:32; uintptr_t paddr:32; } PACKED drives;
uintptr_t pconfig_table:32;
uintptr_t pboot_loader_name:32;
uintptr_t papm_table:32;
struct {
uintptr_t pcontrol_info:32;
uintptr_t pmode_info:32;
uint16_t mode, interface_seg, interface_off, interface_len;
} PACKED vbe;
struct {
uintptr_t paddr;
uint32_t pitch, width, height;
uint8_t bpp;
FramebufferType type;
union {
struct {
uint32_t paddr;
uint16_t num_colors;
} PACKED palette;
struct {
uint8_t red_field_position;
uint8_t red_mask_size;
uint8_t green_field_position;
uint8_t green_mask_size;
uint8_t blue_field_position;
uint8_t blue_mask_size;
} PACKED rgb;
} PACKED;
} PACKED fb;
} PACKED;
struct VBEInfo {
uint32_t signature;
uint16_t version;
uintptr_t vendor_string:32;
uint32_t capabilities;
uintptr_t video_mode_ptr:32;
uint16_t total_memory;
uint16_t oem_software_rev;
uintptr_t oem_vendor_name_ptr:32;
uintptr_t oem_product_name_ptr:32;
uintptr_t oem_product_rev_ptr:32;
uint8_t reserved[222];
uint8_t oem_data[256];
} PACKED;
struct VBEModeInfo {
uint16_t mode_attr;
uint8_t win_attr[2];
uint16_t win_grain;
uint16_t win_size;
uint16_t win_seg[2];
uintptr_t win_scheme:32;
uint16_t logical_scan;
uint16_t h_res;
uint16_t v_res;
uint8_t char_width;
uint8_t char_height;
uint8_t memory_planes;
uint8_t bpp;
uint8_t banks;
uint8_t memory_layout;
uint8_t bank_size;
uint8_t image_pages;
uint8_t page_function;
uint8_t rmask;
uint8_t rpos;
uint8_t gmask;
uint8_t gpos;
uint8_t bmask;
uint8_t bpos;
uint8_t resv_mask;
uint8_t resv_pos;
uint8_t dcm_info;
uintptr_t lfb_ptr:32;
uintptr_t offscreen_ptr:32;
uint16_t offscreen_size;
uint8_t reserved[206];
} PACKED;
struct MmapEnt {
uint32_t size;
void *base;
size_t length;
uint32_t type;
MemoryType type;
} PACKED;
struct Module {
uint32_t start;
......
......@@ -3,6 +3,7 @@
#include "kernlib.hpp"
#include "efi.hpp"
#include "multiboot_info.hpp"
#include "pagetable.hpp"
#include "font-8x16.hpp"
......@@ -203,6 +204,14 @@ void Display::setup() {
instance = new FramebufferDisplay(fb->base, fb->width, fb->height, pixelFormat);
return;
}
const struct Multiboot::Payload *mb = Multiboot::getPayload();
if (mb && (mb->flags & Multiboot::FLAG_VBETAB)) {
const Multiboot::VBEModeInfo *mode = reinterpret_cast<const Multiboot::VBEModeInfo*>(mb->vbe.pmode_info);
if (mode && mode->lfb_ptr) {
instance = new FramebufferDisplay(reinterpret_cast<void*>(mode->lfb_ptr), mode->h_res, mode->v_res, PixelFormatBGRX);
return;
}
}
// Fallback
instance = new ConsoleDisplay();
......
......@@ -9,6 +9,23 @@ class Mutex {
bool state;
public:
Mutex(): state(0) {}
void lock();
void release();
inline void lock() {
asm volatile(
"1:"
"testw $1, %0; jnz 1b;"
"lock btsw $0, %0; jc 1b;"
::"m"(state));
}
inline bool try_lock() {
bool ret = 0;
asm volatile(
"lock btsw $0, %1; jc 1f;"
"mov $1, %0;"
"1:"
:"=r"(ret):"m"(state));
return ret;
}
inline void release() {
asm volatile("movw $0, %0"::"m"(state));
}
};
......@@ -10,4 +10,8 @@ class RAND {
static uint64_t _get64();
public:
template<typename T> static inline T get() { return static_cast<T>(_get64()); }
template<typename T> static inline T get(T max) { return get(0, max); }
template<typename T> static inline T get(T min, T max) {
return min + (get<T>() % (max - min));
}
};
// PhoeniX OS Kernel library mutex functions
// Copyright © 2017 Yury Popov a.k.a. PhoeniX
#include "kernlib.hpp"
void Mutex::lock() {
asm volatile(
"1:"
"mov $1, %%dl;"
"xor %%al, %%al;"
"lock cmpxchgb %%dl, %0;"
"jnz 1b"
::"m"(state)
:"rax","rdx");
}
void Mutex::release() {
asm volatile(
"xor %%al, %%al;"
"lock xchgb %%al, %0"
::"m"(state)
:"rax");
}
......@@ -135,7 +135,6 @@ void ACPI::ParseApic(const Madt *madt) {
Pagetable::map(header + 1);
uint16_t type = header->type;
uint16_t length = header->length;
Pagetable::map(header);
if (type == 0) {
const ApicLocalApic *s = reinterpret_cast<const ApicLocalApic*>(p);
acpiCpuIds[acpiCpuCount++] = s->apicId;
......
......@@ -53,16 +53,20 @@ class Pagetable {
return &page[pml4x];
}
static Entry* find(void *addr, Entry *pagetable) {
static Entry* find(const void *addr, Entry *pagetable) {
return find(uintptr_t(addr), pagetable);
}
} PACKED;
private:
static Entry *pagetable;
static const size_t rsvd_num = 16;
static void* rsvd_pages[rsvd_num];
static Mutex page_mutex;
static uint64_t last_page;
static void* _alloc(uint8_t avl = 0, bool nolow = false);
static void* _map(const void* addr);
static void* _getRsvd();
static void _renewRsvd();
static void init();
public:
......
......@@ -312,7 +312,7 @@ void Interrupts::init() {
ent->iomap_base = sizeof(TSS64_ENT);
gdt->sys_ents[idx] = GDT::SystemEntry(
uintptr_t(tss[idx]), sizeof(TSS64_ENT) + 0x2000,
uintptr_t(tss[idx]), sizeof(TSS64_ENT) + 0x2000 - 1,
0x9, 0, 0, 1, 0, 1, 0, 0);
}
......@@ -326,14 +326,14 @@ void Interrupts::init() {
"pushq $8;"
"lea 1f(%%rip), %%rcx;"
"pushq %%rcx;"
"lgdtq (%q0);"
"lgdtq %0;"
"iretq;"
"1:"
"mov %%ss, %%ax;"
"mov %%ax, %%ds;"
"mov %%ax, %%es;"
"mov %%ax, %%gs;"
::"r"(&gdtreg):"rax", "rcx");
::"m"(gdtreg):"rax", "rcx");
uintptr_t addr;
char *lapic_eoi =
......
This diff is collapsed.
......@@ -17,11 +17,14 @@ static void syscall_puts(uintptr_t strptr) {
static void syscall_exit(int code) {
ProcessManager *manager = ProcessManager::getManager();
Process *process = manager->currentProcess();
void *rsp; asm volatile("mov %%rsp, %q0; and $~0xFFF, %q0":"=r"(rsp));
Pagetable::Entry *pt; asm volatile("mov %%cr3, %q0":"=r"(pt));
Pagetable::Entry *pte = Pagetable::Entry::find(rsp, pt);
asm volatile(
"callq _ZN7Process4exitEi;"
"sti;"
"sti; movq $0, %q2;"
"jmp _ZN14ProcessManager12process_loopEv"
::"D"(process), "S"(code)
::"D"(process), "S"(code), "a"(pte)
);
}
......
......@@ -172,10 +172,10 @@ void ModuleManager::parseInternal() {
}
void ModuleManager::parseInitRD() {
Multiboot::Payload *multiboot = Multiboot::getPayload();
if (!multiboot || (multiboot->flags & Multiboot::MB_FLAG_MODS) == 0) return;
if (!multiboot || (multiboot->flags & Multiboot::FLAG_MODS) == 0) return;
const Multiboot::Module *mods =
reinterpret_cast<const Multiboot::Module*>(uintptr_t(multiboot->pmods_addr));
for (uint32_t i = 0; i < multiboot->mods_count; i++) {
reinterpret_cast<const Multiboot::Module*>(uintptr_t(multiboot->mods.paddr));
for (uint32_t i = 0; i < multiboot->mods.count; i++) {
const char *base = reinterpret_cast<const char*>(uintptr_t(mods[i].start));
const char *top = reinterpret_cast<const char*>(uintptr_t(mods[i].end));
size_t length = size_t(top - base);
......
......@@ -12,10 +12,11 @@ Process::Process() {
id = size_t(-1);
pagetable = nullptr;
entry = 0;
_aslrCode = ((RAND::get<uintptr_t>() << 12) & 0x7FFFFFFF000) | 0x40000000000;
_aslrStack = ((RAND::get<uintptr_t>() << 12) & 0x7FFFFFFF000) | 0x80000000000;
_aslrCode = RAND::get<uintptr_t>(0x80000000llu, 0x100000000llu) << 12;
_aslrStack = RAND::get<uintptr_t>(0x40000000llu, 0x80000000llu) << 12;
}
Process::~Process() {
void *rsp; asm volatile("mov %%rsp, %q0; and $~0xFFF, %q0":"=r"(rsp));
if (pagetable != nullptr) {
PTE addr;
for (uintptr_t ptx = 0; ptx < 512; ptx++) {
......@@ -38,10 +39,11 @@ Process::~Process() {
if (!addr.present)
continue;
void *page = addr.getPtr();
if (uintptr_t(page) == ((ptx << (12 + 9 + 9 + 9))
uintptr_t ptaddr = ((ptx << (12 + 9 + 9 + 9))
| (pdx << (12 + 9 + 9))
| (pdpx << (12 + 9)) | (pml4x << (12))))
continue;
| (pdpx << (12 + 9)) | (pml4x << (12)));
if (page == rsp) continue;
if (uintptr_t(page) == ptaddr) continue;
Pagetable::free(page);
}
Pagetable::free(ppml4e);
......@@ -251,11 +253,11 @@ void Process::startup() {
static const uintptr_t KB4 = 0xFFFFFFFFFFFFF000;
for (uintptr_t addr = uintptr_t(gdt.addr) & KB4;
addr < (uintptr_t(gdt.addr) + gdt.limit); addr += 0x1000) {
addPage(addr, reinterpret_cast<void*>(addr), 5);
addPage(addr, reinterpret_cast<void*>(addr), 1);
}
for (uintptr_t addr = uintptr_t(idt.addr) & KB4;
addr < (uintptr_t(idt.addr) + idt.limit); addr += 0x1000) {
addPage(addr, reinterpret_cast<void*>(addr), 5);
addPage(addr, reinterpret_cast<void*>(addr), 1);
}
Interrupts::REC64 *recs = static_cast<Interrupts::REC64*>(idt.addr);
uintptr_t page = 0;
......@@ -265,7 +267,7 @@ void Process::startup() {
| (uintptr_t(recs[i].offset_high) << 32));
if (page != (handler & KB4)) {
page = handler & KB4;
addPage(page, reinterpret_cast<void*>(page), 5);
addPage(page, reinterpret_cast<void*>(page), 1);
}
}
uintptr_t handler, sc_wrapper;
......@@ -273,8 +275,8 @@ void Process::startup() {
asm volatile("lea _ZN7Syscall7wrapperEv(%%rip), %q0":"=r"(sc_wrapper));
handler &= KB4;
sc_wrapper &= KB4;
addPage(handler, reinterpret_cast<void*>(handler), 5);
addPage(sc_wrapper, reinterpret_cast<void*>(sc_wrapper), 5);
addPage(handler, reinterpret_cast<void*>(handler), 1);
addPage(sc_wrapper, reinterpret_cast<void*>(sc_wrapper), 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);
......@@ -290,22 +292,23 @@ void Process::startup() {
while (gdt_ent < gdt_top) {
uintptr_t base = gdt_ent->getBase();
size_t limit = gdt_ent->getLimit();
if (((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) || (limit != sizeof(TSS64_ENT) + 0x2000)) {
if (((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) || (limit != sizeof(TSS64_ENT) + 0x2000 - 1)) {
gdt_ent++;
continue;
}
uintptr_t page = base & KB4;
addPage(page, reinterpret_cast<void*>(page), 5);
addPage(page + 0x1000, iomap[0], 5);
addPage(page + 0x2000, iomap[1], 5);
GDT::SystemEntry *sysent = reinterpret_cast<GDT::SystemEntry*>(gdt_ent);
base = sysent->getBase();
uintptr_t page = base & KB4;
addPage(page, reinterpret_cast<void*>(page), 1);
addPage(page + 0x1000, iomap[0], 1);
addPage(page + 0x2000, iomap[1], 1);
TSS64_ENT *tss = reinterpret_cast<TSS64_ENT*>(base);
uintptr_t stack = tss->ist[0];
page = stack - 0x1000;
addPage(page, reinterpret_cast<void*>(page), 5);
addPage(page, reinterpret_cast<void*>(page), 3);
gdt_ent = reinterpret_cast<GDT::Entry*>(sysent + 1);
}
......