redo application paging and system calls, rename mercury to hilbert

This commit is contained in:
Benji Dial 2024-01-15 15:44:20 -05:00
parent 7c6a18d77a
commit c9a1266d21
34 changed files with 322 additions and 350 deletions

2
.gitignore vendored
View file

@ -1,5 +1,5 @@
.vscode/ .vscode/
include/mercury/kernel/limine.hpp include/hilbert/kernel/limine.hpp
limine limine
obj obj
out out

View file

@ -1,7 +1,7 @@
#include <mercury/syscall.hpp> #include <hilbert/syscall.hpp>
using mercury::syscall::encoded_color; using hilbert::syscall::encoded_color;
using mercury::syscall::color; using hilbert::syscall::color;
encoded_color *fb; encoded_color *fb;
uint32_t fb_width; uint32_t fb_width;
@ -10,7 +10,7 @@ uint32_t fb_pitch;
int main(int, char **) { int main(int, char **) {
mercury::syscall::get_framebuffer(fb, fb_width, fb_height, fb_pitch); hilbert::syscall::get_framebuffer(fb, fb_width, fb_height, fb_pitch);
for (uint32_t y = 0; y < fb_height; ++y) for (uint32_t y = 0; y < fb_height; ++y)
for (uint32_t x = 0; x < fb_width; ++x) { for (uint32_t x = 0; x < fb_width; ++x) {
color c = { color c = {
@ -18,9 +18,8 @@ int main(int, char **) {
.g = (uint8_t)(y * 255 / fb_height), .g = (uint8_t)(y * 255 / fb_height),
.b = (uint8_t)(x * 255 / fb_width) .b = (uint8_t)(x * 255 / fb_width)
}; };
fb[y * fb_pitch + x] = mercury::syscall::encode_color(c); fb[y * fb_pitch + x] = hilbert::syscall::encode_color(c);
} }
mercury::syscall::draw_framebuffer();
//*(int *)0x12345678 = 0; //*(int *)0x12345678 = 0;
//fb_width = *(uint32_t *)0xffffffffc0000000; //fb_width = *(uint32_t *)0xffffffffc0000000;

View file

@ -18,13 +18,13 @@ SECTIONS {
*(.text .text.*) *(.text .text.*)
} : rx } : rx
. = ALIGN(0x200000); . = ALIGN(4096);
.rodata : { .rodata : {
*(.rodata .rodata.*) *(.rodata .rodata.*)
} : ro } : ro
. = ALIGN(0x200000); . = ALIGN(4096);
.data : { .data : {
*(.data .data.*) *(.data .data.*)

View file

@ -1,11 +1,11 @@
only the first 32GiB of physical memory are considered. this can be changed only the first 32GiB of physical memory are considered. this can be changed
with pram_pages in paging.cpp. vram layout is as follows: with pram_pages in paging.cpp. vram layout is as follows:
0x0000.0000.0000 - 0x0000.001f.ffff: always unmapped 0x0000.0000.0000 - 0x0000.0000.0fff: always unmapped
0x0000.0020.0000 - 0x0000.3fbf.ffff: available to user process 0x0000.0000.1000 - 0x0000.001f.efff: user stack
0x0000.3fc0.0000 - 0x0000.3fdf.ffff: always unmapped 0x0000.001f.f000 - 0x0000.001f.ffff: always unmapped
0x0000.3fe0.0000 - 0x0000.3fff.ffff: user stack 0x0000.0020.0000 - 0x007f.ffff.ffff: available to user process
0x0000.4000.0000 - 0xffff.bfff.ffff: always unmapped 0x0080.0000.0000 - 0xffff.bfff.ffff: always unmapped
0xffff.c000.0000 - 0xffff.ffdf.ffff: available to kernel 0xffff.c000.0000 - 0xffff.ffdf.ffff: available to kernel
0xffff.ffe0.0000 - 0xffff.ffe0.0fff: always unmapped 0xffff.ffe0.0000 - 0xffff.ffe0.0fff: always unmapped
0xffff.ffe0.1000 - 0xffff.ffef.efff: interrupt stack 0xffff.ffe0.1000 - 0xffff.ffef.efff: interrupt stack

View file

@ -20,8 +20,3 @@ get framebuffer:
esi out: pitch esi out: pitch
framebuffer is always 32 bpp. use the encode color syscall framebuffer is always 32 bpp. use the encode color syscall
to encode colors. pitch is in dwords, not in bytes. to encode colors. pitch is in dwords, not in bytes.
draw framebuffer:
rax in: 2
this draws changes to the framebuffer gotten by the get framebuffer
system call. (currently, the entire thing is copied, not just changes.)

View file

@ -1,10 +1,12 @@
#ifndef MERCURY_KERNEL_APPLICATION_HPP #ifndef HILBERT_KERNEL_APPLICATION_HPP
#define MERCURY_KERNEL_APPLICATION_HPP #define HILBERT_KERNEL_APPLICATION_HPP
#include <mercury/kernel/vfile.hpp> #include <hilbert/kernel/vfile.hpp>
#include <cstdint> #include <cstdint>
namespace mercury::kernel::application { //TODO: end application, threading.
namespace hilbert::kernel::application {
enum class app_state { enum class app_state {
running, running,
@ -18,9 +20,10 @@ namespace mercury::kernel::application {
uint64_t *p4; uint64_t *p4;
uint64_t *p3; uint64_t *p3;
uint64_t *p2; uint64_t *p2s[512];
uint64_t **p1s[512];
bool *p2es_to_free_on_exit; bool **p1es_to_free_on_exit[512];
uint64_t p4_paddr; uint64_t p4_paddr;
@ -38,20 +41,15 @@ namespace mercury::kernel::application {
} saved_regs; } saved_regs;
app_instance(); app_instance();
~app_instance();
//2MiB page. vaddr and paddr must be aligned, and vaddr in valid range. //vaddr and paddr must be aligned, and vaddr must be < 0x0080.0000.0000
void map_page(uint64_t vaddr, uint64_t paddr, void map_page(uint64_t vaddr, uint64_t paddr,
bool write, bool execute, bool free_pram_on_exit); bool write, bool execute, bool free_pram_on_exit);
//2MiB pages. returns start of first page. //returns start of first page.
uint64_t get_free_vaddr_pages(uint64_t count); uint64_t get_free_vaddr_pages(uint64_t count);
void create_stack(); //in lower half
void set_instruction_pointer(uint64_t vaddr);
//2MiB pages; only lower half.
uint64_t count_mapped_vram_pages(); uint64_t count_mapped_vram_pages();
}; };

View file

@ -1,16 +1,14 @@
#ifndef MERCURY_KERNEL_FRAMEBUFFER_HPP #ifndef HILBERT_KERNEL_FRAMEBUFFER_HPP
#define MERCURY_KERNEL_FRAMEBUFFER_HPP #define HILBERT_KERNEL_FRAMEBUFFER_HPP
#include <cstdint> #include <cstdint>
namespace mercury::kernel::framebuffer { namespace hilbert::kernel::framebuffer {
extern uint32_t *vaddr;
extern int width; extern int width;
extern int height; extern int height;
extern int dword_pitch;
void init_framebuffer(uint64_t vaddr, uint64_t width, uint64_t height, uint64_t pitch); void init_framebuffer(uint64_t paddr, uint64_t vaddr, uint64_t width, uint64_t height, uint64_t pitch);
typedef uint32_t color; typedef uint32_t color;
color encode_color(uint8_t r, uint8_t g, uint8_t b); color encode_color(uint8_t r, uint8_t g, uint8_t b);

View file

@ -1,12 +1,12 @@
#ifndef MERCURY_KERNEL_PAGING_HPP #ifndef HILBERT_KERNEL_PAGING_HPP
#define MERCURY_KERNEL_PAGING_HPP #define HILBERT_KERNEL_PAGING_HPP
#include <cstdint> #include <cstdint>
//in paging.asm //in paging.asm
extern "C" [[noreturn]] void switch_to_kernel_p4(void (*and_then_jump_to)()); extern "C" [[noreturn]] void switch_to_kernel_p4(void (*and_then_jump_to)());
namespace mercury::kernel::paging { namespace hilbert::kernel::paging {
void mark_all_pram_used(); void mark_all_pram_used();
void mark_all_vram_free(); void mark_all_vram_free();
@ -16,11 +16,12 @@ namespace mercury::kernel::paging {
uint64_t find_unmapped_vram_region(uint64_t page_count); uint64_t find_unmapped_vram_region(uint64_t page_count);
uint64_t encode_pte( uint64_t encode_pte(uint64_t addr, bool user, bool write, bool execute);
uint64_t addr, bool user, bool write, bool execute, bool ps);
void init_kernel_page_tables(uint64_t kernel_offset); void init_kernel_page_tables(uint64_t kernel_offset);
uint64_t take_pram_page();
void map_kernel_stacks(); void map_kernel_stacks();
void map_kernel_page( void map_kernel_page(
@ -39,8 +40,6 @@ namespace mercury::kernel::paging {
extern uint64_t kernel_p4e; extern uint64_t kernel_p4e;
uint64_t take_2mib_pram_page();
} }
#endif #endif

View file

@ -1,10 +1,10 @@
#ifndef MERCURY_KERNEL_STORAGE_HPP #ifndef HILBERT_KERNEL_STORAGE_HPP
#define MERCURY_KERNEL_STORAGE_HPP #define HILBERT_KERNEL_STORAGE_HPP
#include <mercury/kernel/utility.hpp> #include <hilbert/kernel/utility.hpp>
#include <cstdint> #include <cstdint>
namespace mercury::kernel::storage { namespace hilbert::kernel::storage {
typedef uint64_t node_id_t; typedef uint64_t node_id_t;
typedef uint64_t directory_iter_t; typedef uint64_t directory_iter_t;

View file

@ -1,9 +1,9 @@
#ifndef MERCURY_KERNEL_STORAGE_BD_MEMORY_HPP #ifndef HILBERT_KERNEL_STORAGE_BD_MEMORY_HPP
#define MERCURY_KERNEL_STORAGE_BD_MEMORY_HPP #define HILBERT_KERNEL_STORAGE_BD_MEMORY_HPP
#include <mercury/kernel/storage.hpp> #include <hilbert/kernel/storage.hpp>
namespace mercury::kernel::storage::bd { namespace hilbert::kernel::storage::bd {
class memory : public block_device { class memory : public block_device {

View file

@ -1,9 +1,9 @@
#ifndef MERCURY_KERNEL_STORAGE_FS_TARFS_HPP #ifndef HILBERT_KERNEL_STORAGE_FS_TARFS_HPP
#define MERCURY_KERNEL_STORAGE_FS_TARFS_HPP #define HILBERT_KERNEL_STORAGE_FS_TARFS_HPP
#include <mercury/kernel/storage.hpp> #include <hilbert/kernel/storage.hpp>
namespace mercury::kernel::storage::fs { namespace hilbert::kernel::storage::fs {
class tarfs_instance : public file_system_instance { class tarfs_instance : public file_system_instance {

View file

@ -0,0 +1,13 @@
#include <cstdint>
namespace hilbert::kernel::syscall {
typedef void (*syscall_handler)(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx);
void init_syscalls();
//assumes this rax has not been used yet and is < 256.
void add_syscall(uint64_t rax, syscall_handler handler);
}

View file

@ -1,12 +1,12 @@
#ifndef MERCURY_KERNEL_TERMINAL_HPP #ifndef HILBERT_KERNEL_TERMINAL_HPP
#define MERCURY_KERNEL_TERMINAL_HPP #define HILBERT_KERNEL_TERMINAL_HPP
#include <mercury/kernel/framebuffer.hpp> #include <hilbert/kernel/framebuffer.hpp>
#include <mercury/kernel/utility.hpp> #include <hilbert/kernel/utility.hpp>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
namespace mercury::kernel::terminal { namespace hilbert::kernel::terminal {
extern uint8_t *termfont; extern uint8_t *termfont;
extern uint64_t termfont_len; extern uint64_t termfont_len;

View file

@ -1,10 +1,10 @@
#ifndef MERCURY_KERNEL_UTILITY_HPP #ifndef HILBERT_KERNEL_UTILITY_HPP
#define MERCURY_KERNEL_UTILITY_HPP #define HILBERT_KERNEL_UTILITY_HPP
#include <optional> #include <optional>
#include <cstdint> #include <cstdint>
namespace mercury::kernel::utility { namespace hilbert::kernel::utility {
template <class t> template <class t>
static inline t min(t a, t b) { static inline t min(t a, t b) {

View file

@ -1,15 +1,15 @@
#ifndef MERCURY_KERNEL_VFILE_HPP #ifndef HILBERT_KERNEL_VFILE_HPP
#define MERCURY_KERNEL_VFILE_HPP #define HILBERT_KERNEL_VFILE_HPP
#include <mercury/kernel/storage.hpp> #include <hilbert/kernel/storage.hpp>
#include <mercury/kernel/utility.hpp> #include <hilbert/kernel/utility.hpp>
//TODO: mounts points. //TODO: mounts points.
//maybe a two-way map between mount points and targets? one mount point per //maybe a two-way map between mount points and targets? one mount point per
//target and vice versa. only directories may be mount points, and only file //target and vice versa. only directories may be mount points, and only file
//system roots (which must be directories) may be targets. //system roots (which must be directories) may be targets.
namespace mercury::kernel::vfile { namespace hilbert::kernel::vfile {
//a canon path contains no . or empty directory names, and //a canon path contains no . or empty directory names, and
//contains no .. except for at the start of a relative path. //contains no .. except for at the start of a relative path.

View file

@ -1,9 +1,9 @@
#ifndef MERCURY_SYSCALL_HPP #ifndef HILBERT_SYSCALL_HPP
#define MERCURY_SYSCALL_HPP #define HILBERT_SYSCALL_HPP
#include <cstdint> #include <cstdint>
namespace mercury::syscall { namespace hilbert::syscall {
typedef uint32_t encoded_color; typedef uint32_t encoded_color;
@ -19,8 +19,6 @@ namespace mercury::syscall {
uint32_t &width_out, uint32_t &height_out, uint32_t &pitch_out uint32_t &width_out, uint32_t &height_out, uint32_t &pitch_out
); );
extern "C" void draw_framebuffer();
} }
#endif #endif

View file

@ -1,7 +1,7 @@
#include <mercury/kernel/paging.hpp> #include <hilbert/kernel/paging.hpp>
#include <cstddef> #include <cstddef>
namespace mercury::kernel::allocator { namespace hilbert::kernel::allocator {
struct free_entry { struct free_entry {
uint64_t start; uint64_t start;
@ -118,7 +118,7 @@ namespace mercury::kernel::allocator {
} }
using namespace mercury::kernel::allocator; using namespace hilbert::kernel::allocator;
void *_new(size_t len) { void *_new(size_t len) {
if (len == 0) if (len == 0)

View file

@ -1,83 +1,87 @@
#include <mercury/kernel/application.hpp> #include <hilbert/kernel/application.hpp>
#include <mercury/kernel/paging.hpp> #include <hilbert/kernel/paging.hpp>
//TODO - scheduling. //TODO - scheduling.
namespace mercury::kernel::application { namespace hilbert::kernel::application {
app_instance::app_instance() : state(app_state::paused) { app_instance::app_instance()
: state(app_state::paused), framebuffer_vaddr(0) {
framebuffer_vaddr = 0;
uint64_t p3_paddr;
uint64_t p2_paddr;
uint64_t p4_vaddr; uint64_t p4_vaddr;
uint64_t p3_vaddr;
uint64_t p2_vaddr;
paging::map_new_kernel_page(p4_vaddr, p4_paddr); paging::map_new_kernel_page(p4_vaddr, p4_paddr);
paging::map_new_kernel_page(p3_vaddr, p3_paddr);
paging::map_new_kernel_page(p2_vaddr, p2_paddr);
p4 = (uint64_t *)p4_vaddr; p4 = (uint64_t *)p4_vaddr;
uint64_t p3_paddr;
uint64_t p3_vaddr;
paging::map_new_kernel_page(p3_vaddr, p3_paddr);
p3 = (uint64_t *)p3_vaddr; p3 = (uint64_t *)p3_vaddr;
p2 = (uint64_t *)p2_vaddr;
for (int i = 1; i < 511; ++i) for (int i = 1; i < 511; ++i)
p4[i] = 0; p4[i] = 0;
p4[0] = paging::encode_pte(p3_paddr, true, true, true);
p4[511] = paging::kernel_p4e; p4[511] = paging::kernel_p4e;
p4[0] = paging::encode_pte(p3_paddr, true, true, true, false);
for (int i = 1; i < 512; ++i) for (int i = 0; i < 512; ++i) {
p3[i] = 0; p3[i] = 0;
p3[0] = paging::encode_pte(p2_paddr, true, true, true, false); p2s[i] = 0;
p1s[i] = 0;
for (int i = 0; i < 512; ++i) p1es_to_free_on_exit[i] = 0;
p2[i] = 0;
p2es_to_free_on_exit = new bool[512];
} }
app_instance::~app_instance() {
for (int i = 1; i < 512; ++i)
if (p2[i] != 0 && p2es_to_free_on_exit[i]) {
uint64_t paddr = p2[i] & ~0x1fffffULL;
paging::mark_pram_region_free(paddr, paddr + 0x200000);
}
delete[] p2es_to_free_on_exit;
uint64_t p2_paddr = p3[0] & ~0x1fffffULL;
paging::unmap_kernel_page((uint64_t)p2);
paging::mark_pram_region_free(p2_paddr, p2_paddr + 4096);
uint64_t p3_paddr = p4[0] & ~0x1fffffULL;
paging::unmap_kernel_page((uint64_t)p3);
paging::mark_pram_region_free(p3_paddr, p3_paddr + 4096);
paging::unmap_kernel_page((uint64_t)p4);
paging::mark_pram_region_free(p4_paddr, p4_paddr + 4096);
} }
void app_instance::map_page(uint64_t vaddr, uint64_t paddr, void app_instance::map_page(uint64_t vaddr, uint64_t paddr,
bool write, bool execute, bool free_pram_on_exit bool write, bool execute, bool free_pram_on_exit
) { ) {
uint64_t i = vaddr / 0x200000;
p2[i] = paging::encode_pte(paddr, true, write, execute, true); uint64_t i = ((vaddr / 4096) / 512) / 512;
p2es_to_free_on_exit[i] = free_pram_on_exit; uint64_t j = ((vaddr / 4096) / 512) % 512;
uint64_t k = (vaddr / 4096) % 512;
if (p2s[i] == 0) {
uint64_t p2_paddr;
uint64_t p2_vaddr;
paging::map_new_kernel_page(p2_vaddr, p2_paddr);
p3[i] = paging::encode_pte(p2_paddr, true, true, true);
p2s[i] = (uint64_t *)p2_vaddr;
p1s[i] = new uint64_t *[512];
p1es_to_free_on_exit[i] = new bool *[512];
for (int u = 0; u < 512; ++u) {
p2s[i][u] = 0;
p1s[i][u] = 0;
p1es_to_free_on_exit[i][u] = 0;
}
}
if (p2s[i][j] == 0) {
uint64_t p1_paddr;
uint64_t p1_vaddr;
paging::map_new_kernel_page(p1_vaddr, p1_paddr);
p2s[i][j] = paging::encode_pte(p1_paddr, true, true, true);
p1s[i][j] = (uint64_t *)p1_vaddr;
p1es_to_free_on_exit[i][j] = new bool[512];
for (int u = 0; u < 512; ++u) {
p1s[i][j][u] = 0;
p1es_to_free_on_exit[i][j][u] = false;
}
}
p1s[i][j][k] = paging::encode_pte(paddr, true, write, execute);
p1es_to_free_on_exit[i][j][k] = free_pram_on_exit;
} }
uint64_t app_instance::get_free_vaddr_pages(uint64_t count) { uint64_t app_instance::get_free_vaddr_pages(uint64_t count) {
uint64_t start = 1; uint64_t start = 0x200000 / 4096;
uint64_t length = 0; uint64_t length = 0;
while (start + length < 510) { while (start + length <= 0x8000000000 / 4096) {
if (length == count) if (length == count)
return start * 0x200000; return start * 4096;
if (p2[start + length] == 0) int i = ((start + length) / 512) / 512;
int j = ((start + length) / 512) % 512;
int k = (start + length) % 512;
if (p1s[i] == 0 || p1s[i][j] == 0 || p1s[i][j][k] == 0)
++length; ++length;
else { else {
start += length + 1; start += length + 1;
@ -88,27 +92,14 @@ namespace mercury::kernel::application {
return 0; return 0;
} }
void app_instance::create_stack() {
uint64_t stack_paddr = paging::take_2mib_pram_page();
map_page(0x3fe00000, stack_paddr, true, false, true);
for (int i = 0; i < 512; ++i) {
uint64_t vaddr = paging::find_unmapped_vram_region(1);
paging::map_kernel_page(stack_paddr + 512 * i, vaddr, true, false);
for (int j = 0; j < 4096 / 8; ++j)
*(uint64_t *)(vaddr + j * 8) = 0;
paging::unmap_kernel_page(vaddr);
}
saved_regs.rsp = 0x40000000;
}
void app_instance::set_instruction_pointer(uint64_t vaddr) {
saved_regs.rip = vaddr;
}
uint64_t app_instance::count_mapped_vram_pages() { uint64_t app_instance::count_mapped_vram_pages() {
uint64_t count = 0; uint64_t count = 0;
for (int i = 1; i < 512; ++i) for (int i = 0; i < 512; ++i)
if (p2[i] != 0) if (p1s[i] != 0)
for (int j = 0; j < 512; ++j)
if (p1s[i][j] != 0)
for (int k = 0; k < 512; ++k)
if (p1s[i][j][k] != 0)
++count; ++count;
return count; return count;
} }
@ -186,18 +177,19 @@ namespace mercury::kernel::application {
READ(entry_start + 40, 8, &vsize) READ(entry_start + 40, 8, &vsize)
READ(entry_start + 4, 4, &flags) READ(entry_start + 4, 4, &flags)
if (vaddr & 0x1fffff) if (vaddr & 4095)
return create_app_result::app_corrupt; return create_app_result::app_corrupt;
if (file.dir_entry.length < foffset + fsize) if (file.dir_entry.length < foffset + fsize)
return create_app_result::app_corrupt; return create_app_result::app_corrupt;
if (fsize > vsize) if (fsize > vsize)
return create_app_result::app_corrupt; return create_app_result::app_corrupt;
if (vaddr == 0)
if (vaddr < 0x200000)
return create_app_result::app_corrupt; return create_app_result::app_corrupt;
uint64_t vpages = (vsize - 1) / 0x200000 + 1; uint64_t vpages = (vsize - 1) / 4096 + 1;
if (vaddr + vpages * 0x200000 > ((1 << 30) - (4 << 20))) if (vaddr + vpages * 4096 > 0x8000000000)
return create_app_result::app_corrupt; return create_app_result::app_corrupt;
load_info info = { load_info info = {
@ -217,22 +209,20 @@ namespace mercury::kernel::application {
for (unsigned i = 0; i < load_infos.count; ++i) { for (unsigned i = 0; i < load_infos.count; ++i) {
const auto &info = load_infos.buffer[i]; const auto &info = load_infos.buffer[i];
for (uint64_t j = 0; j < info.vpages; ++j) { for (uint64_t j = 0; j < info.vpages; ++j) {
uint64_t paddr = paging::take_2mib_pram_page(); uint64_t paddr = paging::take_pram_page();
out->map_page(info.vaddr + j * 0x200000, paddr, out->map_page(info.vaddr + j * 4096, paddr,
info.writable, info.executable, true); info.writable, info.executable, true);
for (int k = 0; k < 512; ++k) {
uint64_t offset_in_segment = j * 0x200000 + k * 4096;
uint64_t kvaddr = paging::find_unmapped_vram_region(1); uint64_t kvaddr = paging::find_unmapped_vram_region(1);
paging::map_kernel_page(paddr + k * 4096, kvaddr, true, false); paging::map_kernel_page(paddr, kvaddr, true, false);
storage::fs_result result = storage::fs_result::success; storage::fs_result result = storage::fs_result::success;
if (info.fsize > offset_in_segment) { if (info.fsize > j * 4096) {
if (info.fsize >= offset_in_segment + 4096) if (info.fsize >= j * 4096 + 4096)
result = file.read_file( result = file.read_file(
info.foffset + offset_in_segment, 4096, (void *)kvaddr); info.foffset + j * 4096, 4096, (void *)kvaddr);
else { else {
int to_read = info.fsize - offset_in_segment; int to_read = info.fsize - j * 4096;
result = file.read_file( result = file.read_file(
info.foffset + offset_in_segment, to_read, (void *)kvaddr); info.foffset + j * 4096, to_read, (void *)kvaddr);
uint8_t *blank = (uint8_t *)(kvaddr + to_read); uint8_t *blank = (uint8_t *)(kvaddr + to_read);
for (int i = 0; i < 4096 - to_read; ++i) for (int i = 0; i < 4096 - to_read; ++i)
blank[i] = 0; blank[i] = 0;
@ -254,10 +244,20 @@ namespace mercury::kernel::application {
} }
} }
} }
for (uint64_t vaddr = 0x1000; vaddr < 0x1ff000; vaddr += 4096) {
uint64_t paddr = paging::take_pram_page();
uint64_t kvaddr = paging::find_unmapped_vram_region(1);
paging::map_kernel_page(paddr, kvaddr, true, false);
uint8_t *p = (uint8_t *)kvaddr;
for (int i = 0; i < 4096; ++i)
p[i] = 0;
paging::unmap_kernel_page(kvaddr);
out->map_page(vaddr, paddr, true, false, true);
} }
out->create_stack(); out->saved_regs.rsp = 0x1ff000;
out->set_instruction_pointer(entry_point); out->saved_regs.rip = entry_point;
return create_app_result::success; return create_app_result::success;

View file

@ -1,13 +1,13 @@
#include <mercury/kernel/storage/bd/memory.hpp> #include <hilbert/kernel/storage/bd/memory.hpp>
#include <mercury/kernel/storage/fs/tarfs.hpp> #include <hilbert/kernel/storage/fs/tarfs.hpp>
#include <mercury/kernel/application.hpp> #include <hilbert/kernel/application.hpp>
#include <mercury/kernel/framebuffer.hpp> #include <hilbert/kernel/framebuffer.hpp>
#include <mercury/kernel/terminal.hpp> #include <hilbert/kernel/terminal.hpp>
#include <mercury/kernel/limine.hpp> #include <hilbert/kernel/limine.hpp>
#include <mercury/kernel/paging.hpp> #include <hilbert/kernel/paging.hpp>
#include <mercury/kernel/vfile.hpp> #include <hilbert/kernel/vfile.hpp>
using namespace mercury::kernel; using namespace hilbert::kernel;
LIMINE_BASE_REVISION(1) LIMINE_BASE_REVISION(1)
@ -173,8 +173,8 @@ extern "C" [[noreturn]] void entry() {
//set up framebuffer and terminal: //set up framebuffer and terminal:
//TODO: assumes framebuffer is 32-bpp rgb //TODO: assumes framebuffer is 32-bpp rgb
framebuffer::init_framebuffer( framebuffer::init_framebuffer(fb_start, fb_vaddr,
fb_vaddr, framebuffer->width, framebuffer->height, framebuffer->pitch); framebuffer->width, framebuffer->height, framebuffer->pitch);
//switch to kernel p4 //switch to kernel p4

View file

@ -1,20 +1,60 @@
#include <mercury/kernel/framebuffer.hpp> #include <hilbert/kernel/application.hpp>
#include <hilbert/kernel/framebuffer.hpp>
#include <hilbert/kernel/syscall.hpp>
namespace mercury::kernel::framebuffer { namespace hilbert::kernel::framebuffer {
uint32_t *vaddr; static uint64_t paddr;
static uint32_t *vaddr;
int width; int width;
int height; int height;
int dword_pitch; static int dword_pitch;
void init_framebuffer( void encode_color_syscall(
uint64_t vaddr, uint64_t width, uint64_t height, uint64_t pitch uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
) { ) {
rax = (uint64_t)encode_color(
rdi & 0xff, (rdi >> 8) & 0xff, (rdi >> 16) & 0xff);
rdi = 0;
rsi = 0;
rdx = 0;
}
void get_framebuffer_syscall(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
) {
auto *app = application::running_app;
if (app->framebuffer_vaddr == 0) {
uint64_t pages_needed = (dword_pitch * height * 4 - 1) / 4096 + 1;
uint64_t vaddr = app->get_free_vaddr_pages(pages_needed);
for (uint64_t i = 0; i < pages_needed; ++i)
app->map_page(vaddr + i * 4096, paddr + i * 4096, true, false, false);
app->framebuffer_vaddr = vaddr;
}
rax = app->framebuffer_vaddr;
rdi = (uint64_t)(uint32_t)width | ((uint64_t)(uint32_t)height << 32);
rsi = (uint32_t)dword_pitch;
rdx = 0;
}
void init_framebuffer(uint64_t paddr, uint64_t vaddr,
uint64_t width, uint64_t height, uint64_t pitch
) {
//TODO: assumes 32-bpp rgb //TODO: assumes 32-bpp rgb
framebuffer::paddr = paddr;
framebuffer::vaddr = (uint32_t *)vaddr; framebuffer::vaddr = (uint32_t *)vaddr;
framebuffer::width = width; framebuffer::width = width;
framebuffer::height = height; framebuffer::height = height;
dword_pitch = pitch / 4; dword_pitch = pitch / 4;
syscall::add_syscall(0, &encode_color_syscall);
syscall::add_syscall(1, &get_framebuffer_syscall);
} }
color encode_color(uint8_t r, uint8_t g, uint8_t b) { color encode_color(uint8_t r, uint8_t g, uint8_t b) {

View file

@ -1,6 +1,6 @@
#include <mercury/kernel/terminal.hpp> #include <hilbert/kernel/terminal.hpp>
using namespace mercury::kernel; using namespace hilbert::kernel;
struct [[gnu::packed]] exception_info_t { struct [[gnu::packed]] exception_info_t {

View file

@ -1,5 +1,5 @@
#include <mercury/kernel/utility.hpp> #include <hilbert/kernel/utility.hpp>
#include <mercury/kernel/paging.hpp> #include <hilbert/kernel/paging.hpp>
//see also ../documentation/memory.txt //see also ../documentation/memory.txt
@ -7,7 +7,7 @@ extern "C" {
uint64_t __kernel_p4_paddr; uint64_t __kernel_p4_paddr;
} }
namespace mercury::kernel::paging { namespace hilbert::kernel::paging {
static constexpr uint64_t kernel_vram_start = 0xffffffffc0000000; static constexpr uint64_t kernel_vram_start = 0xffffffffc0000000;
static constexpr uint64_t kernel_vram_end = 0xffffffffffe00000; static constexpr uint64_t kernel_vram_end = 0xffffffffffe00000;
@ -38,11 +38,9 @@ namespace mercury::kernel::paging {
uint64_t kernel_p4e; uint64_t kernel_p4e;
uint64_t encode_pte( uint64_t encode_pte(uint64_t addr, bool user, bool write, bool execute) {
uint64_t addr, bool user, bool write, bool execute, bool ps
) {
return (addr & 0x0000ffffffffffff) | (execute ? 0 : (1ULL << 63)) return (addr & 0x0000ffffffffffff) | (execute ? 0 : (1ULL << 63))
| (ps << 7) | (user << 2) | (write << 1) | 1; | (user << 2) | (write << 1) | 1;
} }
void init_kernel_page_tables(uint64_t kernel_offset) { void init_kernel_page_tables(uint64_t kernel_offset) {
@ -50,15 +48,15 @@ namespace mercury::kernel::paging {
for (int i = 0; i < 511; ++i) for (int i = 0; i < 511; ++i)
kernel_p4[i] = 0; kernel_p4[i] = 0;
kernel_p4e = encode_pte( kernel_p4e = encode_pte(
(uint64_t)kernel_p3 - kernel_offset, false, true, true, false); (uint64_t)kernel_p3 - kernel_offset, false, true, true);
kernel_p4[511] = kernel_p4e; kernel_p4[511] = kernel_p4e;
for (int i = 0; i < 511; ++i) for (int i = 0; i < 511; ++i)
kernel_p3[i] = 0; kernel_p3[i] = 0;
kernel_p3[511] = encode_pte( kernel_p3[511] = encode_pte(
(uint64_t)kernel_p2 - kernel_offset, false, true, true, false); (uint64_t)kernel_p2 - kernel_offset, false, true, true);
for (int i = 0; i < 512; ++i) for (int i = 0; i < 512; ++i)
kernel_p2[i] = encode_pte( kernel_p2[i] = encode_pte(
(uint64_t)kernel_p1s + 4096 * i - kernel_offset, false, true, true, false); (uint64_t)kernel_p1s + 4096 * i - kernel_offset, false, true, true);
for (int i = 0; i < 512 * 512; ++i) for (int i = 0; i < 512 * 512; ++i)
kernel_p1s[i] = 0; kernel_p1s[i] = 0;
} }
@ -66,7 +64,7 @@ namespace mercury::kernel::paging {
void map_kernel_page( void map_kernel_page(
uint64_t paddr, uint64_t vaddr, bool write, bool execute) { uint64_t paddr, uint64_t vaddr, bool write, bool execute) {
uint64_t i = (vaddr - kernel_vram_start) / 4096; uint64_t i = (vaddr - kernel_vram_start) / 4096;
kernel_p1s[i] = encode_pte(paddr, false, write, execute, false); kernel_p1s[i] = encode_pte(paddr, false, write, execute);
} }
void unmap_kernel_page(uint64_t vaddr) { void unmap_kernel_page(uint64_t vaddr) {
@ -77,7 +75,7 @@ namespace mercury::kernel::paging {
); );
} }
static uint64_t take_pram_page() { uint64_t take_pram_page() {
for (uint64_t i = 0; i < pram_pages / 64; ++i) for (uint64_t i = 0; i < pram_pages / 64; ++i)
if (~pram_usage_bitmap[i] != 0) if (~pram_usage_bitmap[i] != 0)
for (int j = 0; j < 64; ++j) for (int j = 0; j < 64; ++j)
@ -89,21 +87,6 @@ namespace mercury::kernel::paging {
return 0; return 0;
} }
uint64_t take_2mib_pram_page() {
for (uint64_t i = 0; i < pram_pages / 512; ++i) {
for (int j = 0; j < 8; ++j)
if (pram_usage_bitmap[i * 8 + j] != 0)
goto next_i;
for (int j = 0; j < 8; ++j)
pram_usage_bitmap[i * 8 + j] = ~0ULL;
return 0x200000 * i;
next_i:
;
}
//TODO: handle error
return 0;
}
void map_kernel_stacks() { void map_kernel_stacks() {
for (uint64_t vaddr = syscall_stack_bottom; for (uint64_t vaddr = syscall_stack_bottom;
vaddr < syscall_stack_top; vaddr += 4096) vaddr < syscall_stack_top; vaddr += 4096)

View file

@ -1,6 +1,6 @@
#include <mercury/kernel/storage.hpp> #include <hilbert/kernel/storage.hpp>
namespace mercury::kernel::storage { namespace hilbert::kernel::storage {
bd_result block_device::load_cache_block(uint64_t i) { bd_result block_device::load_cache_block(uint64_t i) {

View file

@ -1,6 +1,6 @@
#include <mercury/kernel/storage/bd/memory.hpp> #include <hilbert/kernel/storage/bd/memory.hpp>
namespace mercury::kernel::storage::bd { namespace hilbert::kernel::storage::bd {
memory::memory(void *buffer, uint64_t buffer_len) memory::memory(void *buffer, uint64_t buffer_len)
: buffer((uint8_t *)buffer) : buffer((uint8_t *)buffer)

View file

@ -1,9 +1,9 @@
#include <mercury/kernel/storage/fs/tarfs.hpp> #include <hilbert/kernel/storage/fs/tarfs.hpp>
//in tarfs_instance, node_id_t and directory_iter_t refer to the number //in tarfs_instance, node_id_t and directory_iter_t refer to the number
//of bytes into the block device that the info sector is located. //of bytes into the block device that the info sector is located.
namespace mercury::kernel::storage::fs { namespace hilbert::kernel::storage::fs {
#define BD_TO_FS(expr) \ #define BD_TO_FS(expr) \
{ \ { \

View file

@ -4,51 +4,7 @@ global start_user_mode
section .text section .text
extern syscall_encode_color extern do_syscall
encode_color_syscall:
call syscall_encode_color
mov edi, eax
xor rax, rax
mov eax, edi
xor rdi, rdi
xor rsi, rsi
xor rdx, rdx
jmp syscall_return
extern syscall_get_fb_vaddr
extern syscall_get_fb_dims
extern syscall_get_fb_pitch
get_framebuffer_syscall:
call syscall_get_fb_vaddr
push rax
call syscall_get_fb_dims
push rax
call syscall_get_fb_pitch
xor rsi, rsi
mov esi, eax
pop rdi
pop rax
xor rdx, rdx
jmp syscall_return
extern syscall_copy_framebuffer
draw_framebuffer_syscall:
call syscall_copy_framebuffer
xor rax, rax
xor rdi, rdi
xor rsi, rsi
xor rdx, rdx
jmp syscall_return
bad_syscall:
xor rax, rax
xor rdi, rdi
xor rsi, rsi
xor rdx, rdx
jmp syscall_return
syscall_entry: syscall_entry:
mov r11, rsp mov r11, rsp
@ -56,15 +12,23 @@ syscall_entry:
push r11 push r11
push rcx push rcx
cmp rax, 0 push rdx
je encode_color_syscall push rsi
cmp rax, 1 push rdi
je get_framebuffer_syscall push rax
cmp rax, 2
je draw_framebuffer_syscall mov rdi, rsp
jmp bad_syscall lea rsi, [rsp + 8]
lea rdx, [rsp + 16]
lea rcx, [rsp + 24]
call do_syscall
pop rax
pop rdi
pop rsi
pop rdx
syscall_return:
xor r8, r8 xor r8, r8
xor r9, r9 xor r9, r9
xor r10, r10 xor r10, r10

View file

@ -1,46 +1,36 @@
#include <mercury/kernel/application.hpp> #include <hilbert/kernel/application.hpp>
#include <mercury/kernel/framebuffer.hpp> #include <hilbert/kernel/framebuffer.hpp>
#include <mercury/kernel/paging.hpp> #include <hilbert/kernel/syscall.hpp>
#include <hilbert/kernel/paging.hpp>
using namespace mercury::kernel; namespace hilbert::kernel::syscall {
extern "C" uint32_t syscall_encode_color(uint32_t c) { syscall_handler handlers[256];
return (uint32_t)framebuffer::encode_color(
c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff void init_syscalls() {
); for (int i = 0; i < 256; ++i)
handlers[i] = 0;
} }
extern "C" uint64_t syscall_get_fb_vaddr() { void add_syscall(uint64_t rax, syscall_handler handler) {
auto *app = application::running_app; handlers[rax] = handler;
if (app->framebuffer_vaddr != 0)
return app->framebuffer_vaddr;
uint64_t fb_len = framebuffer::dword_pitch * framebuffer::height * 4;
uint64_t fb_pages = (fb_len - 1) / 0x200000 + 1;
uint64_t vaddr = app->get_free_vaddr_pages(fb_pages);
for (uint64_t i = 0; i < fb_pages; ++i) {
uint64_t paddr = paging::take_2mib_pram_page();
app->map_page(vaddr + i * 0x200000, paddr, true, false, true);
}
app->framebuffer_vaddr = vaddr;
return vaddr;
} }
extern "C" uint64_t syscall_get_fb_dims() {
return (uint64_t)(uint32_t)framebuffer::width +
((uint64_t)(uint32_t)framebuffer::height << 32);
} }
extern "C" uint32_t syscall_get_fb_pitch() { using namespace hilbert::kernel::syscall;
return (uint32_t)framebuffer::dword_pitch;
extern "C" void do_syscall(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
) {
if (rax < 256 && handlers[rax] != 0)
handlers[rax](rax, rdi, rsi, rdx);
else {
rax = 0;
rdi = 0;
rsi = 0;
rdx = 0;
} }
extern "C" void syscall_copy_framebuffer() {
auto *app = application::running_app;
if (app->framebuffer_vaddr != 0) {
const uint32_t *source = (const uint32_t *)app->framebuffer_vaddr;
for (int y = 0; y < framebuffer::height; ++y)
for (int x = 0; x < framebuffer::width; ++x)
framebuffer::vaddr[y * framebuffer::dword_pitch + x]
= source[y * framebuffer::dword_pitch + x];
}
} }

View file

@ -1,7 +1,7 @@
#include <mercury/kernel/framebuffer.hpp> #include <hilbert/kernel/framebuffer.hpp>
#include <mercury/kernel/terminal.hpp> #include <hilbert/kernel/terminal.hpp>
namespace mercury::kernel::terminal { namespace hilbert::kernel::terminal {
uint8_t *termfont; uint8_t *termfont;
uint64_t termfont_len; uint64_t termfont_len;

View file

@ -1,6 +1,6 @@
#include <mercury/kernel/utility.hpp> #include <hilbert/kernel/utility.hpp>
namespace mercury::kernel::utility { namespace hilbert::kernel::utility {
void mark_bitmap_region_zero( void mark_bitmap_region_zero(
uint64_t *bitmap, uint64_t start_i, uint64_t end_i) { uint64_t *bitmap, uint64_t start_i, uint64_t end_i) {

View file

@ -1,9 +1,9 @@
#include <mercury/kernel/vfile.hpp> #include <hilbert/kernel/vfile.hpp>
//TODO: handle symlink loops nicely in vfile::get_child, //TODO: handle symlink loops nicely in vfile::get_child,
// vfile::get_children, and lookup_path. // vfile::get_children, and lookup_path.
namespace mercury::kernel::vfile { namespace hilbert::kernel::vfile {
void canon_path::parent() { void canon_path::parent() {
if (segments.count != 0) if (segments.count != 0)

View file

@ -1,5 +1,5 @@
TIMEOUT=0 TIMEOUT=0
:Mercury :Hilbert
PROTOCOL=limine PROTOCOL=limine
KERNEL_PATH=boot:///kernel.elf KERNEL_PATH=boot:///kernel.elf

View file

@ -18,14 +18,14 @@ clean:
dist-clean: dist-clean:
rm -rf limine rm -rf limine
rm -f include/mercury/kernel/limine.hpp rm -f include/hilbert/kernel/limine.hpp
limine: limine:
git clone --depth=1 -b v6.x-branch \ git clone --depth=1 -b v6.x-branch \
https://github.com/limine-bootloader/limine.git limine https://github.com/limine-bootloader/limine.git limine
cd limine && ./bootstrap && ./configure -q --enable-bios --enable-bios-cd cd limine && ./bootstrap && ./configure -q --enable-bios --enable-bios-cd
+make -C limine +make -C limine
cp limine/limine.h include/mercury/kernel/limine.hpp cp limine/limine.h include/hilbert/kernel/limine.hpp
obj/kernel/entry.cpp.o: kernel/entry.cpp limine obj/kernel/entry.cpp.o: kernel/entry.cpp limine
@mkdir -p $(@D) @mkdir -p $(@D)

View file

@ -1,4 +1,4 @@
mercury is a 64-bit hobby operating system. to build and test it, you will need hilbert is a 64-bit hobby operating system. to build and test it, you will need
some dependencies. these can be installed on debian with: some dependencies. these can be installed on debian with:
apt install g++ gcc gdb git make nasm qemu-system-x86 xorriso apt install g++ gcc gdb git make nasm qemu-system-x86 xorriso
then, just run "make -jx", replacing x with the number of threads to use while then, just run "make -jx", replacing x with the number of threads to use while

View file

@ -28,8 +28,3 @@ get_framebuffer:
pop rcx pop rcx
mov dword [rcx], esi mov dword [rcx], esi
ret ret
draw_framebuffer:
mov rax, 2
syscall
ret