Implement Ring 3 process subsystem with syscalls and context switching (AI)
Add complete user-mode process support: - TSS (tss.c/h): Task State Segment for Ring 3->0 transitions, installed as GDT entry 5 (selector 0x28). ESP0 updated per-process for kernel stack switching. - Process management (process.c/h): Process table with up to 64 processes. process_create() clones kernel page directory, maps user code at 0x08048000 and user stack at 0xBFFFF000, copies flat binary code. Round-robin scheduler via schedule_tick() modifies the interrupt frame in-place for zero-copy context switching. - System calls (syscall.c/h): INT 0x80 dispatcher with 8 syscalls: SYS_EXIT, SYS_WRITE (to debug port + VGA), SYS_READ, SYS_FORK, SYS_GETPID, SYS_YIELD, SYS_WAITPID, SYS_EXEC. IDT gate at 0x80 uses DPL=3 (flags 0xEE) so user code can invoke it. - Assembly stubs (interrupts.S): isr128 for INT 0x80, tss_flush for loading the Task Register, enter_usermode for initial iret to Ring 3. - Paging extensions (paging.c/h): paging_clone_directory() to create per-process page directories, paging_map_page_in() for mapping into non-active directories, paging_switch_directory() for CR3 switching. - GDT expanded from 5 to 6 entries to accommodate TSS descriptor. gdt_set_gate() exposed in header for TSS initialization. - ISR handler routes timer IRQ (32) to scheduler and INT 0x80 to syscall dispatcher. Exception handler now prints EIP/CS/ERR for debugging. - Kernel boots a test user program that writes 'Hello from Ring 3!' via SYS_WRITE and exits with code 42 via SYS_EXIT. Verified working in QEMU. Context switching approach: Timer/syscall interrupts save all registers via the ISR stub. schedule_tick() copies saved_regs between PCBs and overwrites the interrupt frame, so the existing iret restores the next process's state without separate switch assembly.
This commit is contained in:
42
src/syscall.h
Normal file
42
src/syscall.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file syscall.h
|
||||
* @brief System call interface.
|
||||
*
|
||||
* Defines system call numbers and the kernel-side handler. User-mode
|
||||
* processes invoke system calls via INT 0x80 with the call number in EAX
|
||||
* and arguments in EBX, ECX, EDX, ESI, EDI.
|
||||
*/
|
||||
|
||||
#ifndef SYSCALL_H
|
||||
#define SYSCALL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "isr.h"
|
||||
|
||||
/** System call numbers. */
|
||||
#define SYS_EXIT 0 /**< Exit the process. Arg: exit code in EBX. */
|
||||
#define SYS_WRITE 1 /**< Write to a file descriptor. fd=EBX, buf=ECX, len=EDX. */
|
||||
#define SYS_READ 2 /**< Read from a file descriptor. fd=EBX, buf=ECX, len=EDX. */
|
||||
#define SYS_FORK 3 /**< Fork the current process. */
|
||||
#define SYS_GETPID 4 /**< Get current process ID. */
|
||||
#define SYS_YIELD 5 /**< Yield the CPU. */
|
||||
#define SYS_WAITPID 6 /**< Wait for a child process. pid=EBX. */
|
||||
#define SYS_EXEC 7 /**< Execute a program. path=EBX, argv=ECX. */
|
||||
|
||||
/** Total number of system calls. */
|
||||
#define NUM_SYSCALLS 8
|
||||
|
||||
/**
|
||||
* Initialize the system call handler.
|
||||
* Installs INT 0x80 in the IDT.
|
||||
*/
|
||||
void init_syscalls(void);
|
||||
|
||||
/**
|
||||
* System call dispatcher (called from the INT 0x80 handler).
|
||||
*
|
||||
* @param regs Register state at the time of the interrupt.
|
||||
*/
|
||||
void syscall_handler(registers_t *regs);
|
||||
|
||||
#endif /* SYSCALL_H */
|
||||
Reference in New Issue
Block a user