1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| #define USERMODE_STACK_SIZE 0x2000 #define RET_TO_KERNEL_IRQ 0x20
uint64_t run_in_user(usermode_func func, unsigned int fault_vector, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, bool *raised_vector) { extern char ret_to_kernel; uint64_t rax = 0; static unsigned char user_stack[USERMODE_STACK_SIZE];
... set_idt_entry(RET_TO_KERNEL_IRQ, &ret_to_kernel, 3); ...
asm volatile ( "mov %%rsp, %[rsp0]\n\t" "mov %[user_ds], %%ax\n\t" "mov %%ax, %%ds\n\t" "mov %%ax, %%es\n\t" "pushq %[user_ds]\n\t" "pushq %[user_stack_top]\n\t" "pushfq\n\t" "pushq %[user_cs]\n\t" "pushq $user_mode\n\t" "iretq\n"
"user_mode:\n\t" "push %%rbx\n\t" "push %%rcx\n\t" "push %%rdx\n\t" "push %%r8\n\t" "push %%r9\n\t" "push %%r10\n\t" "push %%r11\n\t" "push %%rdi\n\t" "push %%rsi\n\t" "mov %[arg1], %%rdi\n\t" "mov %[arg2], %%rsi\n\t" "mov %[arg3], %%rdx\n\t" "mov %[arg4], %%rcx\n\t" "call *%[func]\n\t" "pop %%rsi\n\t" "pop %%rdi\n\t" "pop %%r11\n\t" "pop %%r10\n\t" "pop %%r9\n\t" "pop %%r8\n\t" "pop %%rdx\n\t" "pop %%rcx\n\t" "pop %%rbx\n\t" "int %[kernel_entry_vector]\n\t" "ret_to_kernel:\n\t" "mov %[rsp0], %%rsp\n\t" : "+a"(rax), [rsp0]"=m"(tss[0].rsp0) : [arg1]"m"(arg1), [arg2]"m"(arg2), [arg3]"m"(arg3), [arg4]"m"(arg4), [func]"m"(func), [user_ds]"i"(USER_DS), [user_cs]"i"(USER_CS), [user_stack_top]"r"(user_stack + sizeof(user_stack)), [kernel_entry_vector]"i"(RET_TO_KERNEL_IRQ) : "rsi", "rdi", "rcx", "rdx");
return rax; }
|