feat(boot+shell): add bootable disk image, unified scheduler and interactive user-space shell

- Implement Limine v8 boot protocol requests in dedicated PT_LOAD RW segment
- Configure IOPL=3 and SSE in arch setup for Ring 3 drivers and libc
- Unify scheduler context switching via switch_to and preempt_tick
- Support dual-source keyboard/serial input in sys_key_read
- Add automated 'make image' and 'make run' targets for instant QEMU launch
- Complete interactive UNIX-like shell (osh) with built-in commands & ramdisk
This commit is contained in:
RarDog
2026-09-02 19:47:57 +03:00
parent ca3555bd09
commit eed05c1eca
17 changed files with 452 additions and 217 deletions
+51 -8
View File
@@ -1,14 +1,15 @@
/* opencoreC - Thread Context Switch */
/* opencoreC - Thread Context Switch & Entry Trampoline */
.global switch_to
.global thread_entry_trampoline
.section .text
/*
* void switch_to(uint64_t **prev_rsp_ptr, uint64_t *next_rsp);
* RDI = pointer to current thread's stored RSP
* RSI = target thread's RSP
* switch_to(uint64_t *prev_rsp_ptr, uint64_t next_rsp)
* RDI = &current_thread.context.rsp (save current RSP here)
* RSI = next thread's saved RSP
*/
switch_to:
/* Push callee-saved registers of outgoing thread */
/* Save callee-saved registers of outgoing thread */
push rbp
push rbx
push r12
@@ -16,13 +17,13 @@ switch_to:
push r14
push r15
/* Save current stack pointer */
/* Save RSP of outgoing thread */
mov [rdi], rsp
/* Load target stack pointer */
/* Load RSP of incoming thread */
mov rsp, rsi
/* Pop callee-saved registers of incoming thread */
/* Restore callee-saved registers of incoming thread */
pop r15
pop r14
pop r13
@@ -31,3 +32,45 @@ switch_to:
pop rbp
ret
/*
* thread_entry_trampoline:
* Jumped to via 'ret' in switch_to when a newly created thread runs for the first time.
* When create_user_thread created the stack:
* R12 was populated with user_rsp
* R13 was populated with entry_rip
*/
thread_entry_trampoline:
/* Set user data segments (0x18 | 3 = 0x1B) */
mov ax, 0x1B
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
/* Build hardware IRETQ frame on kernel stack */
push 0x1B /* User SS */
push r12 /* User RSP */
push 0x3202 /* RFLAGS (IF=1, IOPL=3 for hardware drivers) */
push 0x23 /* User CS (0x20 | 3 = 0x23) */
push r13 /* User RIP */
/* Clear all general-purpose registers */
xor rax, rax
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
xor rsi, rsi
xor rdi, rdi
xor rbp, rbp
xor r8, r8
xor r9, r9
xor r10, r10
xor r11, r11
xor r12, r12
xor r13, r13
xor r14, r14
xor r15, r15
/* Transition to Ring 3 */
iretq
+36 -17
View File
@@ -2,25 +2,46 @@
.global syscall_entry
.extern kernel_syscall_dispatcher
/* Per-CPU scratch: user RSP saved here on syscall entry */
.section .bss
.align 16
user_scratch_rsp:
.quad 0
kernel_temp_stack:
.skip 4096
kernel_temp_stack_top:
.align 8
.global cpu0_scratch_user_rsp
cpu0_scratch_user_rsp: .quad 0
.section .text
/*
* syscall_entry:
* On entry (SYSCALL from Ring 3):
* RCX = user RIP
* R11 = user RFLAGS
* RAX = syscall number
* RDI,RSI,RDX,R10,R8,R9 = args
* RSP = user RSP
*
* Strategy:
* 1. Save user RSP into scratch area
* 2. Load kernel RSP from TSS.RSP0 via gdt.rs TSS symbol
* 3. Build SyscallRegisters on kernel stack
* 4. Dispatch to Rust handler
* 5. Restore & sysretq
*/
syscall_entry:
/* Save user stack pointer */
mov [rip + user_scratch_rsp], rsp
lea rsp, [rip + kernel_temp_stack_top]
/* Save user RSP */
mov [rip + cpu0_scratch_user_rsp], rsp
/* Save user RIP (in RCX) and user RFLAGS (in R11) */
/* Load kernel stack from TSS.rsp0.
* TSS is exported as 'TSS' from gdt.rs.
* Layout: _reserved1(u32=4 bytes), rsp0(u64=8 bytes)
* So TSS.rsp0 is at offset 4 from TSS start.
*/
lea rsp, [rip + TSS]
mov rsp, [rsp + 4]
/* Push user RIP and RFLAGS */
push rcx
push r11
/* Save argument and volatile registers to construct SyscallRegisters */
/* Push syscall arguments as SyscallRegisters */
push rax
push rdi
push rsi
@@ -29,11 +50,10 @@ syscall_entry:
push r9
push r10
/* Pass pointer to SyscallRegisters struct in RDI */
mov rdi, rsp
call kernel_syscall_dispatcher
/* Restore registers (rax, rdx, r8 may have return values from dispatcher) */
/* Restore args */
pop r10
pop r9
pop r8
@@ -42,12 +62,11 @@ syscall_entry:
pop rdi
pop rax
/* Restore user RIP and RFLAGS */
/* Restore user context */
pop r11
pop rcx
/* Restore user stack */
mov rsp, [rip + user_scratch_rsp]
/* Restore user RSP */
mov rsp, [rip + cpu0_scratch_user_rsp]
/* Return to Ring 3 */
sysretq
+4 -8
View File
@@ -4,7 +4,7 @@
.section .text
timer_isr_entry:
/* 1. Save all general-purpose registers to form a complete interrupt context frame */
/* 1. Save all general-purpose registers to form complete interrupt context frame */
push rax
push rbx
push rcx
@@ -21,14 +21,10 @@ timer_isr_entry:
push r14
push r15
/* 2. Pass current saved stack pointer in RDI */
mov rdi, rsp
/* 2. Call handler in Rust (sends EOI and invokes sched.preempt_tick) */
call timer_interrupt_handler
/* 3. Switch stack pointer to returned value (RAX contains next thread's RSP) */
mov rsp, rax
/* 4. Restore all general-purpose registers */
/* 3. Restore all general-purpose registers */
pop r15
pop r14
pop r13
@@ -45,5 +41,5 @@ timer_isr_entry:
pop rbx
pop rax
/* 5. Return from interrupt (IRETQ restores RIP, CS, RFLAGS, RSP, SS) */
/* 4. Return from interrupt (IRETQ restores RIP, CS, RFLAGS, RSP, SS) */
iretq