Code: Select all
__attribute__((naked, noreturn))
void switch_to_user_mode_1(uint64_t stack_addr, uint64_t code_addr)
{
asm volatile(" \
push $0x23 \n\
push %0 \n\
push $0x202 \n\
push $0x1B \n\
push %1 \n\
sti \n\
iretq \n\
" :: "r"(stack_addr), "r"(code_addr));
}
```
I also add `sti` to start interrupt before iretq although iretq may store interrupt bit.
I have uheap_alloc function which allocate address at user space with user permission paging enabled in those locations.My System has interrupt system call 172 which print some message which can be called by `int 172`. I have checked it from kernel space it works.
To test and jump into a user space instruction I have written following assembly code:
Code: Select all
section .text
extern is_user_mode
extern print_dec
global user_stub
global user_stub_end
user_stub:
int 172
call is_user_mode
mov rdi, rax
call print_dec
.hang:
jmp .hang
user_stub_end:
Code: Select all
uint64_t user_stub_size = ((uint64_t)&user_stub_end - (uint64_t)&user_stub);
uint64_t user_addr = (uint64_t) uheap_alloc(user_stub_size); // Allocate a page in user space
if (!user_addr) return 0;
memcpy((void *)user_addr, (void *)&user_stub, user_stub_size); // Copy function code
uint64_t stack_addr = ((uint64_t) uheap_alloc(STACK_SIZE)) + STACK_SIZE;
// I also made stack writable and non executable and user_addr readable and executable
switch_to_user_mode_1(stack_top_addr, code_addr);
Edit: GitHub
I do not understand what should I do to debug. I tried to debug by gdb to breaking the switch_to_user_mode_1 function after jumping into iretq showing some memory address with ? sign.
Someone said asm is better than c version of switch_to_user_mode
Code: Select all
section .text
global switch_to_user_mode ; using switch_to_user_mode(uint64_t stack_addr, uint64_t code_addr) in c
switch_to_user_mode:
cli ; Disable interrupts
mov ax, 0x23 ; User-mode data segment (ring 3)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push 0x23 ; SS = user data segment
push rdi ; Stack address
pushfq ; Push RFLAGS (Interrupts enabled) 0x202
push 0x1B ; CS = user code segment (ring 3)
push rsi ; Code address (Entry point)
sti ; Enable interrupts
iretq ; Return to user mode
