feat(userspace): userspace support
build: updated CMakeLists to build and copy to initramfs wip(syscalls): initial syscalls chore(ksh/kfetch): minor changes chore(gitignore): added initramfs/*
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define CPU_FEAT_FPU (1ULL << 0)
|
||||
@@ -24,7 +24,11 @@
|
||||
#define CPU_FEAT_HYPERVISOR (1ULL << 30)
|
||||
|
||||
typedef struct {
|
||||
i32 features;
|
||||
u64 user_rsp;
|
||||
u64 kernel_rsp;
|
||||
u64 self;
|
||||
|
||||
u64 features;
|
||||
char vendor[13];
|
||||
u32 family;
|
||||
u32 model;
|
||||
@@ -32,5 +36,5 @@ typedef struct {
|
||||
|
||||
extern cpu_info g_cpu;
|
||||
|
||||
void cpuinfo_init();
|
||||
void cpuinfo_init(u64 kernel_stack_top);
|
||||
bool cpu_has(u64 feature);
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MSR_EFER 0xC0000080
|
||||
#define MSR_STAR 0xC0000081
|
||||
#define MSR_LSTAR 0xC0000082
|
||||
#define MSR_FMASK 0xC0000084
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
#define EFER_SCE 0x01 // System Call Enable
|
||||
|
||||
typedef enum {
|
||||
SYS_EXIT,
|
||||
SYS_EXEC,
|
||||
SYS_WRITE,
|
||||
} syscalls;
|
||||
|
||||
void syscall_init();
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
bool exec_init(const char* path);
|
||||
void init_task_entry();
|
||||
@@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
void jump_to_userspace(void* entry, void* user_stack_top);
|
||||
@@ -26,16 +26,8 @@ typedef struct {
|
||||
const unsigned char* base;
|
||||
} SG_Font;
|
||||
|
||||
typedef struct {
|
||||
SG_Context *ctx;
|
||||
SG_Point pos;
|
||||
const char *title;
|
||||
} SG_Window;
|
||||
|
||||
void sg_init(SG_Context *ctx);
|
||||
u32 sg_get_pixel(SG_Context *ctx, SG_Point *p);
|
||||
void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img);
|
||||
void sg_draw_rect(SG_Context *ctx, SG_Point *p, u32 w, u32 h, u32 color);
|
||||
void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font);
|
||||
SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position);
|
||||
void composer_task();
|
||||
void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font);
|
||||
@@ -4,6 +4,9 @@
|
||||
#include "types.h"
|
||||
#include <cpuinfo.h>
|
||||
|
||||
#define MSR_GS_BASE 0xC0000101
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
cpu_info g_cpu = {0};
|
||||
|
||||
static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) {
|
||||
@@ -13,7 +16,18 @@ static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u3
|
||||
);
|
||||
}
|
||||
|
||||
void cpuinfo_init() {
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
void cpuinfo_init(u64 kernel_stack_top) {
|
||||
g_cpu.kernel_rsp = kernel_stack_top;
|
||||
g_cpu.self = (u64)&g_cpu;
|
||||
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
|
||||
|
||||
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(0, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
@@ -27,6 +27,7 @@ stack_guard:
|
||||
global stack_bottom
|
||||
stack_bottom:
|
||||
resb 16384
|
||||
global stack_top
|
||||
stack_top:
|
||||
|
||||
section .text.entry
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright (c) 2026 0xKarinyash
|
||||
|
||||
bits 64
|
||||
|
||||
extern syscall_dispatch
|
||||
global syscall_entry
|
||||
|
||||
section .text
|
||||
|
||||
syscall_entry:
|
||||
swapgs
|
||||
mov [gs:0], rsp ; saving users rsp in g_cpu.user_rsp
|
||||
mov rsp, [gs:8] ; load kernel rsp from g_cpu.kernel_rsp
|
||||
|
||||
push qword [gs:0]
|
||||
push r11 ; rflags
|
||||
push rcx ; rip
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
push r10
|
||||
push r8
|
||||
push r9
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
; preparing c code
|
||||
; c waits rdi, rsi, rdx, rcx, r8, r9
|
||||
; user sent rax, rdi, rsi, rdx, r10, r8 (rax=id)
|
||||
|
||||
mov r9, r8 ; 6th arg
|
||||
mov r8, r10 ; 5th arg
|
||||
mov rcx, rdx ; 4th arg
|
||||
mov rdx, rsi ; 3rd arg
|
||||
mov rsi, rdi ; 2nd arg
|
||||
mov rdi, rax ; 1st arg (id)
|
||||
|
||||
call syscall_dispatch
|
||||
|
||||
; restoring context except RAX (result there)
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r9
|
||||
pop r8
|
||||
pop r10
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbx
|
||||
pop rbp
|
||||
pop rcx ; rip
|
||||
pop r11 ; rflags
|
||||
add rsp, 8 ; skip rsp
|
||||
|
||||
mov [gs:8], rsp
|
||||
mov rsp, [gs:0]
|
||||
swapgs
|
||||
|
||||
o64 sysret
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <cpuinfo.h>
|
||||
#include <syscall.h>
|
||||
#include <types.h>
|
||||
#include <drivers/console.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
static inline u64 rdmsr(u32 msr) {
|
||||
u32 low, high;
|
||||
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||
return ((u64)high << 32) | low;
|
||||
}
|
||||
|
||||
extern void syscall_entry();
|
||||
|
||||
void syscall_init() {
|
||||
u64 efer = rdmsr(MSR_EFER);
|
||||
wrmsr(MSR_EFER, efer | 1); // Enabling SCE in EFER. Just enabling 0 bit
|
||||
|
||||
// setting up STAR
|
||||
// 32:47 kernel selector (0x08)
|
||||
// 48:64 user selector (0x01 cuz sysret adds +16 for CS and +8 for SS)
|
||||
u64 star = (0x13ULL << 48) | (0x08ULL << 32);
|
||||
wrmsr(MSR_STAR, star);
|
||||
|
||||
wrmsr(MSR_LSTAR, (u64)syscall_entry); // setting handler adress
|
||||
|
||||
// masking flags (IA32_FMASK)
|
||||
// 9 bit for finterrupts in syscall (IF) and few more necessary flags
|
||||
wrmsr(MSR_FMASK, 0x200); // masking only IF
|
||||
|
||||
if (g_cpu.kernel_rsp == 0) {
|
||||
void* stack_phys = pmm_alloc_page();
|
||||
g_cpu.kernel_rsp = (u64)stack_phys + HHDM_OFFSET + 4096;
|
||||
}
|
||||
|
||||
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
|
||||
}
|
||||
|
||||
u64 syscall_dispatch(u64 id, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) {
|
||||
switch (id) {
|
||||
case SYS_EXIT: {
|
||||
kprintf("\n[Dewar] process exited with code %d", arg1);
|
||||
while(1) __asm__ ("hlt"); // stub
|
||||
return 0;
|
||||
}
|
||||
case SYS_EXEC: {
|
||||
kprintf("\n[Dewar] process called exec syscall");
|
||||
return 0; // stub as well
|
||||
}
|
||||
case SYS_WRITE: {
|
||||
kprintf("%s", (char*)arg1);
|
||||
return 0;
|
||||
}
|
||||
default: kprintf("[Dewar] Unknown syscall %d\n", id); return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <core/loader.h>
|
||||
#include <core/userspace.h>
|
||||
#include <core/scheduler.h>
|
||||
|
||||
#include <shell/ksh.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/memory.h>
|
||||
|
||||
#include <fs/vfs.h>
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <types.h>
|
||||
|
||||
extern u64* pml4_kernel;
|
||||
|
||||
bool exec_init(const char* path) {
|
||||
kprintf("[Loader] loading %s...\n", path);
|
||||
fs_node* file = vfs_open(path);
|
||||
if (!file) {
|
||||
kprintf("[Loader] Error: %s not found in initramfs!\n", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 virt_code = 0x400000;
|
||||
u64 virt_stack = 0x800000;
|
||||
u64 stack_size = 8192;
|
||||
|
||||
u64 bytes_left = file->len;
|
||||
u64 offset = 0;
|
||||
u64 page_idx = 0;
|
||||
|
||||
while (bytes_left > 0) {
|
||||
void* phys = pmm_alloc_page();
|
||||
if (!phys) {
|
||||
kprintf("Loader: OOM!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
vmm_map_page(pml4_kernel, (u64)phys, virt_code + (page_idx * 4096), PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
|
||||
void* k_ptr = (void*)(HHDM_OFFSET + (u64)phys);
|
||||
memset(k_ptr, 0, 4096);
|
||||
|
||||
u64 chunk = (bytes_left > 4096) ? 4096 : bytes_left;
|
||||
vfs_read(file, offset, chunk, (u8*)k_ptr);
|
||||
|
||||
bytes_left -= chunk;
|
||||
offset += chunk;
|
||||
page_idx++;
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < (stack_size / 4096); i++) {
|
||||
void* phys = pmm_alloc_page();
|
||||
vmm_map_page(pml4_kernel, (u64)phys, virt_stack + (i * 4096), PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
memset((void*)(HHDM_OFFSET + (u64)phys), 0, 4096);
|
||||
}
|
||||
|
||||
__asm__ volatile(
|
||||
"mov %%cr3, %%rax\n\t"
|
||||
"mov %%rax, %%cr3\n\t"
|
||||
::: "rax", "memory"
|
||||
);
|
||||
|
||||
kprintf("[Loader] Transferring control to userspace...\n");
|
||||
jump_to_userspace((void*)virt_code, (void*)(virt_stack + stack_size));
|
||||
|
||||
return true; // unreachable
|
||||
}
|
||||
|
||||
void init_task_entry() {
|
||||
if (!exec_init("/init")) {
|
||||
kprintf("FATAL: Could not load /init\n");
|
||||
sched_spawn(ksh);
|
||||
|
||||
while(1) __asm__("hlt");
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <mm/heap.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <gdt.h>
|
||||
|
||||
task* curr_task = nullptr;
|
||||
@@ -68,6 +69,7 @@ u64 sched_next(u64 curr_rsp) {
|
||||
|
||||
curr_task = next;
|
||||
tss.rsp0 = curr_task->kernel_stack_top;
|
||||
g_cpu.kernel_rsp = curr_task->kernel_stack_top;
|
||||
return curr_task->rsp;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <core/userspace.h>
|
||||
#include <types.h>
|
||||
|
||||
#define USER_DS (0x18 | 3)
|
||||
#define USER_CS (0x20 | 3)
|
||||
#define RFLAGS_IF 0x202
|
||||
|
||||
void jump_to_userspace(void* entry, void* user_stack_top) {
|
||||
__asm__ volatile (
|
||||
"mov %0, %%ds\n"
|
||||
"mov %0, %%es\n"
|
||||
"mov %0, %%fs\n"
|
||||
:: "r" ((u64)USER_DS) : "memory"
|
||||
);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushq %0\n" // SS (User Data Selector)
|
||||
"pushq %1\n" // RSP (User Stack Pointer)
|
||||
"pushq %2\n" // RFLAGS
|
||||
"pushq %3\n" // CS (User Code Selector)
|
||||
"pushq %4\n" // RIP (Entry Point)
|
||||
"iretq\n"
|
||||
:
|
||||
: "r" ((u64)USER_DS),
|
||||
"r" ((u64)user_stack_top),
|
||||
"r" ((u64)RFLAGS_IF),
|
||||
"r" ((u64)USER_CS),
|
||||
"r" ((u64)entry)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
@@ -8,11 +8,8 @@
|
||||
#include <mm/memory.h>
|
||||
|
||||
#define SHITGUI_TRANSPARENCY_KEY 0xFF00FF
|
||||
#define SHITGUI_MAX_WINDOWS_AMOUNT 64
|
||||
|
||||
SG_Context* main_context;
|
||||
SG_Window* windows[SHITGUI_MAX_WINDOWS_AMOUNT]; // нет блять линукс
|
||||
u64 windows_amount = 0;
|
||||
|
||||
void sg_init(SG_Context *ctx) {
|
||||
main_context = ctx;
|
||||
@@ -85,64 +82,4 @@ void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Fon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position) {
|
||||
if (windows_amount >= SHITGUI_MAX_WINDOWS_AMOUNT) return nullptr;
|
||||
SG_Context* ctx = nullptr;
|
||||
u32* fb = nullptr;
|
||||
SG_Window* window = nullptr;
|
||||
|
||||
ctx = (SG_Context*)malloc(sizeof(SG_Context));
|
||||
if (!ctx) goto fail; // goto is GOOD for cleaning up in C stfu.
|
||||
// Mainline linux kernel contains 100k gotos
|
||||
|
||||
fb = malloc(size->x * size->y * sizeof(u32));
|
||||
if (!fb) goto fail;
|
||||
memset(fb, 0, size->x * size->y * sizeof(u32));
|
||||
|
||||
window = (SG_Window*)malloc(sizeof(SG_Window));
|
||||
if (!window) goto fail;
|
||||
|
||||
ctx->fb = fb;
|
||||
ctx->height = size->y;
|
||||
ctx->width = size->x;
|
||||
ctx->pitch = size->x;
|
||||
|
||||
|
||||
window->ctx = ctx;
|
||||
window->title = title;
|
||||
window->pos.x = position->x;
|
||||
window->pos.y = position->y;
|
||||
|
||||
windows[windows_amount] = window;
|
||||
windows_amount++;
|
||||
|
||||
return window;
|
||||
|
||||
fail:
|
||||
if (ctx) free(ctx);
|
||||
if (fb) free(fb);
|
||||
if (window) free(window);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void render_window(SG_Context *ctx, SG_Window *window) {
|
||||
SG_Image img = {0};
|
||||
img.buffer = window->ctx->fb;
|
||||
if (!img.buffer) panic("No img buffer found");
|
||||
img.height = window->ctx->height;
|
||||
img.width = window->ctx->width;
|
||||
|
||||
sg_put_img(ctx, &window->pos, &img);
|
||||
}
|
||||
|
||||
void composer_task() {
|
||||
while (true) {
|
||||
for (u64 i = 0; i < windows_amount; i++) {
|
||||
render_window(main_context, windows[i]);
|
||||
}
|
||||
yield(1);
|
||||
}
|
||||
}
|
||||
+21
-5
@@ -2,7 +2,7 @@
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include "bootinfo.h"
|
||||
#include "core/rand.h"
|
||||
|
||||
#include <shell/ksh.h>
|
||||
|
||||
#include <types.h>
|
||||
@@ -15,11 +15,14 @@
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/splash.h>
|
||||
#include <core/rand.h>
|
||||
#include <core/loader.h>
|
||||
|
||||
#include <gdt.h>
|
||||
#include <idt.h>
|
||||
#include <pic.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
@@ -32,6 +35,7 @@
|
||||
#define BG_COLOR 0x111111
|
||||
|
||||
extern u64 _kernel_end;
|
||||
extern void* stack_top;
|
||||
static SG_Context sg_ctx;
|
||||
|
||||
void kmain(Bootinfo* info) {
|
||||
@@ -42,7 +46,7 @@ void kmain(Bootinfo* info) {
|
||||
|
||||
if (info->magic != BOOTINFO_MAGIC) panic("Corrupt bootinfo!");
|
||||
|
||||
cpuinfo_init();
|
||||
cpuinfo_init((u64)&stack_top);
|
||||
kprintf("Got CPUINFO\n");
|
||||
rng_init();
|
||||
kprintf("RNG initialized\n");
|
||||
@@ -64,6 +68,7 @@ void kmain(Bootinfo* info) {
|
||||
kprintf("Scheduler initialized\n");
|
||||
sg_init(&sg_ctx);
|
||||
kprintf("Shitgui initialized\n");
|
||||
syscall_init();
|
||||
|
||||
info = (Bootinfo*)PHYS_TO_HHDM((u64)info);
|
||||
|
||||
@@ -85,9 +90,20 @@ void kmain(Bootinfo* info) {
|
||||
|
||||
show_splash(&sg_ctx);
|
||||
|
||||
sched_spawn(composer_task);
|
||||
sched_spawn(ksh);
|
||||
if (!info->initramfs.addr) kprintf("^rWARNING^!: Failed to load ^yinitramfs^!, VFS is empty.\n\n");
|
||||
bool staying_in_ksh = false;
|
||||
if (!info->initramfs.addr) {
|
||||
kprintf("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n");
|
||||
staying_in_ksh = true;
|
||||
}
|
||||
|
||||
kprintf("Press any key to stay in ^gksh^!. \nPress ^yenter^! to continue booting in ring 3\n");
|
||||
char c = '\n';
|
||||
c = console_getc();
|
||||
if (c != '\n') staying_in_ksh = true;
|
||||
|
||||
if (staying_in_ksh) sched_spawn(ksh);
|
||||
else sched_spawn(init_task_entry);
|
||||
|
||||
__asm__ volatile("sti");
|
||||
|
||||
while (true) __asm__ volatile("hlt");
|
||||
|
||||
@@ -35,7 +35,7 @@ void cmd_kfetch() {
|
||||
kprintf("^p %s ^!\t\t^gUptime^!: %d seconds\n^!", ascii_logo[4], uptime_s);
|
||||
kprintf("^p %s ^!\t\t^gShell^!: ksh\n^!", ascii_logo[5]);
|
||||
kprintf("^p %s ^!\t\t^gDE^!: shitgui\n^!", ascii_logo[6]);
|
||||
kprintf("^p %s ^!\t\t^gCPU^!: %s\n^!", ascii_logo[7], g_cpu.vendor);
|
||||
kprintf("^p %s ^!\t\t^gCPU^!: %s (^yFamily^!: %d; ^yModel^!: %d)\n^!", ascii_logo[7], g_cpu.vendor, g_cpu.family, g_cpu.model);
|
||||
kprintf("\n\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
// contents of this file will be changed CONSTANTLY
|
||||
// im just testing new stuff here
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include "mm/vmm.h"
|
||||
#include <mm/pmm.h>
|
||||
#include <shell/dbgcmd.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
extern u64* pml4_kernel;
|
||||
|
||||
#define USER_DS (0x18 | 3)
|
||||
#define USER_CS (0x20 | 3)
|
||||
#define RFLAGS_IF 0x202
|
||||
|
||||
void jump_to_userspace(void* entry, void* user_stack_top) {
|
||||
__asm__ volatile (
|
||||
"mov %0, %%ds\n"
|
||||
"mov %0, %%es\n"
|
||||
"mov %0, %%fs\n"
|
||||
"mov %0, %%gs\n"
|
||||
:: "r" ((u64)USER_DS) : "memory"
|
||||
);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushq %0\n" // SS (User Data Selector)
|
||||
"pushq %1\n" // RSP (User Stack Pointer)
|
||||
"pushq %2\n" // RFLAGS
|
||||
"pushq %3\n" // CS (User Code Selector)
|
||||
"pushq %4\n" // RIP (Entry Point)
|
||||
"iretq\n" // jump
|
||||
:
|
||||
: "r" ((u64)USER_DS),
|
||||
"r" ((u64)user_stack_top),
|
||||
"r" ((u64)RFLAGS_IF),
|
||||
"r" ((u64)USER_CS),
|
||||
"r" ((u64)entry)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
u64 debug() {
|
||||
void* phys_code = pmm_alloc_page();
|
||||
void* phys_stack = pmm_alloc_page();
|
||||
u64 virt_code = 0x400000;
|
||||
u64 virt_stack = 0x800000;
|
||||
|
||||
vmm_map_page(pml4_kernel, (u64)phys_code, virt_code, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
vmm_map_page(pml4_kernel, (u64)phys_stack, virt_stack, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
u8* kernel_view = (u8*)(HHDM_OFFSET + phys_code);
|
||||
kernel_view[0] = 0xEB; // jmp
|
||||
kernel_view[1] = 0xFE; // to self
|
||||
kprintf("Jumping to userspace. Goodbye.");
|
||||
jump_to_userspace((void*)virt_code, (void*)(virt_stack + 4096));
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user