mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
memory fixes
This commit is contained in:
parent
a4e0a42042
commit
c5c77ce734
12 changed files with 156 additions and 105 deletions
BIN
boredos.iso
BIN
boredos.iso
Binary file not shown.
BIN
build/idt.o
BIN
build/idt.o
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
Binary file not shown.
BIN
build/ps2.o
BIN
build/ps2.o
Binary file not shown.
|
|
@ -29,9 +29,9 @@ isr%2_wrapper:
|
||||||
push rbx
|
push rbx
|
||||||
push rcx
|
push rcx
|
||||||
push rdx
|
push rdx
|
||||||
push rbp
|
|
||||||
push rdi
|
|
||||||
push rsi
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rbp
|
||||||
push r8
|
push r8
|
||||||
push r9
|
push r9
|
||||||
push r10
|
push r10
|
||||||
|
|
@ -57,9 +57,9 @@ isr%2_wrapper:
|
||||||
pop r10
|
pop r10
|
||||||
pop r9
|
pop r9
|
||||||
pop r8
|
pop r8
|
||||||
pop rsi
|
|
||||||
pop rdi
|
|
||||||
pop rbp
|
pop rbp
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
pop rdx
|
pop rdx
|
||||||
pop rcx
|
pop rcx
|
||||||
pop rbx
|
pop rbx
|
||||||
|
|
@ -134,9 +134,9 @@ exception_common:
|
||||||
push rbx
|
push rbx
|
||||||
push rcx
|
push rcx
|
||||||
push rdx
|
push rdx
|
||||||
push rbp
|
|
||||||
push rdi
|
|
||||||
push rsi
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rbp
|
||||||
push r8
|
push r8
|
||||||
push r9
|
push r9
|
||||||
push r10
|
push r10
|
||||||
|
|
@ -163,9 +163,9 @@ exception_common:
|
||||||
pop r10
|
pop r10
|
||||||
pop r9
|
pop r9
|
||||||
pop r8
|
pop r8
|
||||||
pop rsi
|
|
||||||
pop rdi
|
|
||||||
pop rbp
|
pop rbp
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
pop rdx
|
pop rdx
|
||||||
pop rcx
|
pop rcx
|
||||||
pop rbx
|
pop rbx
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,18 @@ static uint32_t get_timestamp(void) {
|
||||||
|
|
||||||
// Sorts the block list by address. This is crucial for efficient merging of free blocks.
|
// Sorts the block list by address. This is crucial for efficient merging of free blocks.
|
||||||
static void sort_block_list() {
|
static void sort_block_list() {
|
||||||
|
bool swapped;
|
||||||
for (int i = 0; i < block_count - 1; i++) {
|
for (int i = 0; i < block_count - 1; i++) {
|
||||||
for (int j = i + 1; j < block_count; j++) {
|
swapped = false;
|
||||||
if ((uintptr_t)block_list[i].address > (uintptr_t)block_list[j].address) {
|
for (int j = 0; j < block_count - i - 1; j++) {
|
||||||
MemBlock tmp = block_list[i];
|
if ((uintptr_t)block_list[j].address > (uintptr_t)block_list[j + 1].address) {
|
||||||
block_list[i] = block_list[j];
|
MemBlock tmp = block_list[j];
|
||||||
block_list[j] = tmp;
|
block_list[j] = block_list[j + 1];
|
||||||
|
block_list[j + 1] = tmp;
|
||||||
|
swapped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!swapped) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,19 +171,24 @@ void* kmalloc_aligned(size_t size, size_t alignment) {
|
||||||
size_t padding = aligned_addr - block_start;
|
size_t padding = aligned_addr - block_start;
|
||||||
|
|
||||||
if (block_size >= size + padding) {
|
if (block_size >= size + padding) {
|
||||||
void* ptr = (void*)aligned_addr;
|
int needed_slots = 0;
|
||||||
|
if (padding > 0) needed_slots++;
|
||||||
size_t remaining_size = block_size - (size + padding);
|
size_t remaining_size = block_size - (size + padding);
|
||||||
|
if (remaining_size > 0) {
|
||||||
// The original free block becomes the trailing free part.
|
needed_slots++;
|
||||||
block_list[i].address = (void*)(aligned_addr + size);
|
} else {
|
||||||
block_list[i].size = remaining_size;
|
// The current slot will be reused for the allocation.
|
||||||
if (remaining_size == 0) {
|
|
||||||
for (int j = i; j < block_count - 1; j++) block_list[j] = block_list[j+1];
|
|
||||||
block_count--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new block for the allocation.
|
if (block_count + needed_slots > MAX_ALLOCATIONS) {
|
||||||
if (block_count >= MAX_ALLOCATIONS) continue;
|
continue; // Cannot fit metadata for this split
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ptr = (void*)aligned_addr;
|
||||||
|
|
||||||
|
// Perform the split
|
||||||
|
if (remaining_size > 0) {
|
||||||
|
|
||||||
block_list[block_count].address = ptr;
|
block_list[block_count].address = ptr;
|
||||||
block_list[block_count].size = size;
|
block_list[block_count].size = size;
|
||||||
block_list[block_count].allocated = true;
|
block_list[block_count].allocated = true;
|
||||||
|
|
@ -187,15 +196,24 @@ void* kmalloc_aligned(size_t size, size_t alignment) {
|
||||||
block_list[block_count].timestamp = get_timestamp();
|
block_list[block_count].timestamp = get_timestamp();
|
||||||
block_count++;
|
block_count++;
|
||||||
|
|
||||||
// Create a new block for the leading padding if it exists.
|
block_list[i].address = (void*)(aligned_addr + size);
|
||||||
|
block_list[i].size = remaining_size;
|
||||||
|
block_list[i].allocated = false;
|
||||||
|
} else {
|
||||||
|
block_list[i].address = ptr;
|
||||||
|
block_list[i].size = size;
|
||||||
|
block_list[i].allocated = true;
|
||||||
|
block_list[i].allocation_id = ++allocation_counter;
|
||||||
|
block_list[i].timestamp = get_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
if (padding > 0) {
|
if (padding > 0) {
|
||||||
if (block_count < MAX_ALLOCATIONS) {
|
|
||||||
block_list[block_count].address = (void*)block_start;
|
block_list[block_count].address = (void*)block_start;
|
||||||
block_list[block_count].size = padding;
|
block_list[block_count].size = padding;
|
||||||
block_list[block_count].allocated = false;
|
block_list[block_count].allocated = false;
|
||||||
|
block_list[block_count].allocation_id = 0;
|
||||||
block_count++;
|
block_count++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sort_block_list();
|
sort_block_list();
|
||||||
|
|
||||||
|
|
@ -237,8 +255,20 @@ void kfree(void *ptr) {
|
||||||
|
|
||||||
total_allocated -= block_list[block_idx].size;
|
total_allocated -= block_list[block_idx].size;
|
||||||
block_list[block_idx].allocated = false;
|
block_list[block_idx].allocated = false;
|
||||||
|
block_list[block_idx].allocation_id = 0;
|
||||||
|
|
||||||
// Merge with next block if it's free and physically adjacent
|
// Merge adjacent blocks. We sort first to make adjacency checking trivial.
|
||||||
|
sort_block_list();
|
||||||
|
|
||||||
|
// Re-find the block (it might have moved during sort)
|
||||||
|
for (int i = 0; i < block_count; i++) {
|
||||||
|
if (block_list[i].address == ptr) {
|
||||||
|
block_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge with next block if possible
|
||||||
if (block_idx + 1 < block_count && !block_list[block_idx + 1].allocated) {
|
if (block_idx + 1 < block_count && !block_list[block_idx + 1].allocated) {
|
||||||
uintptr_t current_end = (uintptr_t)block_list[block_idx].address + block_list[block_idx].size;
|
uintptr_t current_end = (uintptr_t)block_list[block_idx].address + block_list[block_idx].size;
|
||||||
uintptr_t next_start = (uintptr_t)block_list[block_idx + 1].address;
|
uintptr_t next_start = (uintptr_t)block_list[block_idx + 1].address;
|
||||||
|
|
@ -249,7 +279,7 @@ void kfree(void *ptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge with previous block if it's free and physically adjacent
|
// Merge with previous block if possible
|
||||||
if (block_idx > 0 && !block_list[block_idx - 1].allocated) {
|
if (block_idx > 0 && !block_list[block_idx - 1].allocated) {
|
||||||
uintptr_t prev_end = (uintptr_t)block_list[block_idx - 1].address + block_list[block_idx - 1].size;
|
uintptr_t prev_end = (uintptr_t)block_list[block_idx - 1].address + block_list[block_idx - 1].size;
|
||||||
uintptr_t current_start = (uintptr_t)block_list[block_idx].address;
|
uintptr_t current_start = (uintptr_t)block_list[block_idx].address;
|
||||||
|
|
@ -257,8 +287,6 @@ void kfree(void *ptr) {
|
||||||
block_list[block_idx - 1].size += block_list[block_idx].size;
|
block_list[block_idx - 1].size += block_list[block_idx].size;
|
||||||
for (int i = block_idx; i < block_count - 1; i++) block_list[i] = block_list[i + 1];
|
for (int i = block_idx; i < block_count - 1; i++) block_list[i] = block_list[i + 1];
|
||||||
block_count--;
|
block_count--;
|
||||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,6 +326,7 @@ void* krealloc(void *ptr, size_t new_size) {
|
||||||
|
|
||||||
MemStats memory_get_stats(void) {
|
MemStats memory_get_stats(void) {
|
||||||
MemStats stats;
|
MemStats stats;
|
||||||
|
mem_memset(&stats, 0, sizeof(MemStats));
|
||||||
|
|
||||||
stats.total_memory = memory_pool_size;
|
stats.total_memory = memory_pool_size;
|
||||||
stats.used_memory = total_allocated;
|
stats.used_memory = total_allocated;
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,19 @@ void process_create(void* entry_point, bool is_user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t* process_create_elf(const char* filepath, const char* args_str) {
|
process_t* process_create_elf(const char* filepath, const char* args_str) {
|
||||||
if (process_count >= MAX_PROCESSES) return NULL;
|
process_t *new_proc = NULL;
|
||||||
|
|
||||||
|
// Find an available slot
|
||||||
|
for (int i = 0; i < MAX_PROCESSES; i++) {
|
||||||
|
if (processes[i].pid == 0xFFFFFFFF || i >= process_count) {
|
||||||
|
new_proc = &processes[i];
|
||||||
|
if (i >= process_count) process_count = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_proc) return NULL;
|
||||||
|
|
||||||
process_t *new_proc = &processes[process_count];
|
|
||||||
new_proc->pid = next_pid++;
|
new_proc->pid = next_pid++;
|
||||||
new_proc->is_user = true;
|
new_proc->is_user = true;
|
||||||
|
|
||||||
|
|
@ -248,8 +258,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
|
||||||
new_proc->user_stack_alloc = stack;
|
new_proc->user_stack_alloc = stack;
|
||||||
new_proc->rsp = (uint64_t)stack_ptr;
|
new_proc->rsp = (uint64_t)stack_ptr;
|
||||||
|
|
||||||
// We only increment process_count after success
|
// Slot is already counted in process_count if new, or reused.
|
||||||
process_count++;
|
|
||||||
|
|
||||||
// Add to linked list
|
// Add to linked list
|
||||||
new_proc->next = current_process->next;
|
new_proc->next = current_process->next;
|
||||||
|
|
@ -291,13 +300,17 @@ uint64_t process_schedule(uint64_t current_rsp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t process_terminate_current(void) {
|
uint64_t process_terminate_current(void) {
|
||||||
if (!current_process) return 0;
|
uint64_t rflags;
|
||||||
|
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||||
|
|
||||||
|
if (!current_process) {
|
||||||
|
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Cleanup side effects
|
// 1. Cleanup side effects
|
||||||
extern Window win_cmd;
|
extern Window win_cmd;
|
||||||
if (current_process->ui_window && (current_process->ui_window != &win_cmd)) {
|
if (current_process->ui_window && (current_process->ui_window != &win_cmd)) {
|
||||||
extern void serial_write(const char *str);
|
|
||||||
serial_write("PROC: Terminating proc with window\n");
|
|
||||||
wm_remove_window((Window *)current_process->ui_window);
|
wm_remove_window((Window *)current_process->ui_window);
|
||||||
current_process->ui_window = NULL;
|
current_process->ui_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -324,13 +337,14 @@ uint64_t process_terminate_current(void) {
|
||||||
|
|
||||||
if (prev == current_process) {
|
if (prev == current_process) {
|
||||||
// Only one process (should be kernel), cannot terminate.
|
// Only one process (should be kernel), cannot terminate.
|
||||||
|
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||||
return to_delete->rsp;
|
return to_delete->rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev->next = to_delete->next;
|
prev->next = to_delete->next;
|
||||||
current_process = to_delete->next;
|
current_process = to_delete->next;
|
||||||
|
|
||||||
// Mark slot as freeish (simple version)
|
// Mark slot as free
|
||||||
to_delete->pid = 0xFFFFFFFF;
|
to_delete->pid = 0xFFFFFFFF;
|
||||||
|
|
||||||
// 4. Load context for the NEXT process
|
// 4. Load context for the NEXT process
|
||||||
|
|
@ -343,13 +357,17 @@ uint64_t process_terminate_current(void) {
|
||||||
paging_switch_directory(current_process->pml4_phys);
|
paging_switch_directory(current_process->pml4_phys);
|
||||||
|
|
||||||
// 5. Actually free the memory (after switching state to avoid issues)
|
// 5. Actually free the memory (after switching state to avoid issues)
|
||||||
if (to_delete->kernel_stack_alloc) kfree(to_delete->kernel_stack_alloc);
|
// We only safely free the user stack. Immediate freeing of the current
|
||||||
|
// kernel stack is unsafe while we are still running on it.
|
||||||
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
|
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
|
||||||
|
|
||||||
// NOTE: In a real system we would also free all physical pages
|
// Clear pointers to avoid double-free during slot reuse
|
||||||
// used by the user page table. For now we just free the stacks.
|
to_delete->user_stack_alloc = NULL;
|
||||||
|
to_delete->kernel_stack_alloc = NULL; // Leak the small kernel stack for safety
|
||||||
|
|
||||||
return current_process->rsp;
|
uint64_t next_rsp = current_process->rsp;
|
||||||
|
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||||
|
return next_rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_push_gui_event(process_t *proc, gui_event_t *ev) {
|
void process_push_gui_event(process_t *proc, gui_event_t *ev) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
struct FAT32_FileHandle;
|
struct FAT32_FileHandle;
|
||||||
|
|
||||||
// Registers saved on the stack by interrupts/exceptions
|
// Registers saved on the stack by interrupts/exceptions
|
||||||
typedef struct {
|
typedef struct registers_t {
|
||||||
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
||||||
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
|
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
|
||||||
uint64_t int_no, err_code;
|
uint64_t int_no, err_code;
|
||||||
|
|
|
||||||
|
|
@ -131,20 +131,12 @@ static void user_window_key(Window *win, char c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||||
extern void cmd_write(const char *str);
|
extern void cmd_write(const char *str);
|
||||||
extern void serial_write(const char *str);
|
extern void serial_write(const char *str);
|
||||||
extern void cmd_process_finished(void);
|
|
||||||
|
|
||||||
if (syscall_num == 1) { // SYS_WRITE
|
if (syscall_num == 1) { // SYS_WRITE
|
||||||
cmd_write((const char*)arg2);
|
cmd_write((const char*)arg2);
|
||||||
} else if (syscall_num == 0 || syscall_num == 60) { // SYS_EXIT
|
|
||||||
uint64_t next_rsp = process_terminate_current();
|
|
||||||
extern void context_switch_to(uint64_t rsp);
|
|
||||||
context_switch_to(next_rsp);
|
|
||||||
|
|
||||||
// This point is never reached
|
|
||||||
while(1);
|
|
||||||
} else if (syscall_num == 3) { // SYS_GUI
|
} else if (syscall_num == 3) { // SYS_GUI
|
||||||
int cmd = (int)arg1;
|
int cmd = (int)arg1;
|
||||||
process_t *proc = process_get_current();
|
process_t *proc = process_get_current();
|
||||||
|
|
@ -501,11 +493,7 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
|
||||||
serial_write((const char *)arg2);
|
serial_write((const char *)arg2);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (syscall_num == 10) { // SYS_KILL
|
} else if (syscall_num == 10) { // SYS_KILL
|
||||||
// Simplified kill: just terminate current for now
|
return 0; // Handled in outer
|
||||||
uint64_t next_rsp = process_terminate_current();
|
|
||||||
extern void context_switch_to(uint64_t rsp);
|
|
||||||
context_switch_to(next_rsp);
|
|
||||||
while(1);
|
|
||||||
} else if (syscall_num == 9) { // SYS_SBRK
|
} else if (syscall_num == 9) { // SYS_SBRK
|
||||||
int incr = (int)arg1;
|
int incr = (int)arg1;
|
||||||
process_t *proc = process_get_current();
|
process_t *proc = process_get_current();
|
||||||
|
|
@ -739,3 +727,18 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t syscall_handler_c(registers_t *regs) {
|
||||||
|
uint64_t syscall_num = regs->rax;
|
||||||
|
|
||||||
|
// Check for context-switching syscalls
|
||||||
|
if (syscall_num == 0 || syscall_num == 60 || syscall_num == 10) { // EXIT or KILL
|
||||||
|
return process_terminate_current();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal syscalls
|
||||||
|
regs->rax = syscall_handler_inner(regs->rax, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8);
|
||||||
|
|
||||||
|
// Return current RSP to assembly wrapper
|
||||||
|
return (uint64_t)regs;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
typedef struct Window Window;
|
typedef struct Window Window;
|
||||||
|
typedef struct registers_t registers_t;
|
||||||
|
|
||||||
// MSRs used for syscalls in x86_64
|
// MSRs used for syscalls in x86_64
|
||||||
#define MSR_EFER 0xC0000080
|
#define MSR_EFER 0xC0000080
|
||||||
|
|
@ -38,7 +39,7 @@ typedef struct Window Window;
|
||||||
#define FS_CMD_CHDIR 13
|
#define FS_CMD_CHDIR 13
|
||||||
|
|
||||||
void syscall_init(void);
|
void syscall_init(void);
|
||||||
uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5);
|
uint64_t syscall_handler_c(registers_t *regs);
|
||||||
|
|
||||||
// Mouse event helpers for WM
|
// Mouse event helpers for WM
|
||||||
void syscall_send_mouse_move_event(Window *win, int x, int y, uint8_t buttons);
|
void syscall_send_mouse_move_event(Window *win, int x, int y, uint8_t buttons);
|
||||||
|
|
|
||||||
|
|
@ -16,63 +16,63 @@ section .text
|
||||||
|
|
||||||
syscall_entry:
|
syscall_entry:
|
||||||
; 1. Switch to Kernel Stack
|
; 1. Switch to Kernel Stack
|
||||||
; Use scratch temporarily to pivot (Risk: Task switch here is rare but possible)
|
|
||||||
mov [rel user_rsp_scratch], rsp
|
mov [rel user_rsp_scratch], rsp
|
||||||
mov rsp, [rel kernel_syscall_stack]
|
mov rsp, [rel kernel_syscall_stack]
|
||||||
|
|
||||||
; 2. Save User RSP on per-process kernel stack
|
; 2. Build iretq frame (compatible with registers_t)
|
||||||
push qword [rel user_rsp_scratch]
|
push 0x1B ; SS (User Data)
|
||||||
|
push qword [rel user_rsp_scratch] ; RSP
|
||||||
|
push r11 ; RFLAGS (captured by syscall)
|
||||||
|
push 0x23 ; CS (User Code)
|
||||||
|
push rcx ; RIP (return address from syscall)
|
||||||
|
|
||||||
; 3. Save preserved registers (System V ABI)
|
push 0 ; err_code
|
||||||
|
push 0 ; int_no (can be used for syscall vector)
|
||||||
|
|
||||||
|
; 3. Save all registers in registers_t order
|
||||||
|
push rax
|
||||||
push rbx
|
push rbx
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
push rbp
|
push rbp
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
push r11
|
||||||
push r12
|
push r12
|
||||||
push r13
|
push r13
|
||||||
push r14
|
push r14
|
||||||
push r15
|
push r15
|
||||||
|
|
||||||
; 4. Save RCX (RIP) and R11 (RFLAGS)
|
; 4. Call C handler with registers_t*
|
||||||
push rcx
|
mov rdi, rsp
|
||||||
push r11
|
|
||||||
|
|
||||||
; Shuffling for SYS V C ABI:
|
|
||||||
; arg5: R9 (remains R9 as 6th arg in C)
|
|
||||||
; arg4: R8 (was R9)
|
|
||||||
; arg3: RCX (was R10)
|
|
||||||
; arg2: RDX (was RSI)
|
|
||||||
; arg1: RSI (was RDI)
|
|
||||||
; num: RDI (was RAX)
|
|
||||||
|
|
||||||
mov r9, r8 ; arg5
|
|
||||||
mov r8, r10 ; arg4
|
|
||||||
mov rcx, rdx ; arg3
|
|
||||||
mov rdx, rsi ; arg2
|
|
||||||
mov rsi, rdi ; arg1
|
|
||||||
mov rdi, rax ; syscall_num
|
|
||||||
|
|
||||||
; 5. Call C handler
|
|
||||||
sti
|
sti
|
||||||
call syscall_handler_c
|
call syscall_handler_c
|
||||||
cli
|
cli
|
||||||
|
|
||||||
; 6. Restore RCX and R11
|
; 5. Switch to the resulting RSP (might be different if task switched)
|
||||||
pop r11
|
mov rsp, rax
|
||||||
pop rcx
|
|
||||||
|
|
||||||
; 7. Restore preserved registers
|
; 6. Restore and return via iretq
|
||||||
pop r15
|
pop r15
|
||||||
pop r14
|
pop r14
|
||||||
pop r13
|
pop r13
|
||||||
pop r12
|
pop r12
|
||||||
|
pop r11
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
pop rbp
|
pop rbp
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
pop rbx
|
pop rbx
|
||||||
|
pop rax
|
||||||
; 8. Restore User RSP from kernel stack
|
add rsp, 16 ; drop int_no/err_code
|
||||||
pop rsp
|
iretq
|
||||||
|
|
||||||
; 9. Return to User Mode (sysret)
|
|
||||||
or r11, 0x200 ; Force Interrupts enabled
|
|
||||||
o64 sysret
|
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
global kernel_syscall_stack
|
global kernel_syscall_stack
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue