/* opencoreC - Ring 3 User Mode Transition (IRETQ) */ .global enter_user_mode .extern set_kernel_stack .section .text /* * void enter_user_mode(uint64_t entry_rip, uint64_t user_rsp, uint64_t pml4_paddr, uint64_t kernel_stack_top); * RDI = entry_rip * RSI = user_rsp * RDX = pml4_paddr * RCX = kernel_stack_top */ enter_user_mode: /* 1. Save kernel stack in TSS (RSP0) for future interrupts/syscalls */ push rdi push rsi push rdx mov rdi, rcx call set_kernel_stack pop rdx pop rsi pop rdi /* 2. Switch to User Address Space (PML4) */ mov cr3, rdx /* 3. Build IRETQ Stack Frame: * [RSP + 32] = SS (User Data: 0x18 | 3 = 0x1B) * [RSP + 24] = RSP (User Stack Pointer) * [RSP + 16] = RFLAGS (Interrupt Flag Enabled: 0x202) * [RSP + 8] = CS (User Code: 0x20 | 3 = 0x23) * [RSP + 0] = RIP (User Entry Point) */ mov ax, 0x1B mov ds, ax mov es, ax mov fs, ax mov gs, ax push 0x1B /* User SS */ push rsi /* User RSP */ push 0x0202 /* RFLAGS (IF enabled) */ push 0x23 /* User CS */ push rdi /* User RIP */ /* 4. Clear 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 /* 5. Jump to Ring 3 */ iretq