65 lines
1.5 KiB
ArmAsm
65 lines
1.5 KiB
ArmAsm
/* 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
|