tasking: add simple base for running things in ring 3
This commit is contained in:
@@ -94,3 +94,24 @@ switchProcess:
|
||||
; |------------------------|
|
||||
|
||||
ret
|
||||
|
||||
global jump_usermode
|
||||
extern test_user_function
|
||||
jump_usermode:
|
||||
mov ax, (4 * 8) | 3 ; ring 3 data with bottom 2 bits set for ring 3
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax ; SS is handled by iret
|
||||
|
||||
; and eax, ~0x80000000
|
||||
; mov cr0, eax
|
||||
|
||||
; set up the stack frame iret expects
|
||||
mov eax, esp
|
||||
push (4 * 8) | 3 ; data selector
|
||||
push eax ; current esp
|
||||
pushf ; eflags
|
||||
push (3 * 8) | 3 ; code selector (ring 3 code with bottom 2 bits set for ring 3)
|
||||
push test_user_function ; instruction address to return to
|
||||
iret
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
; TODO: maybe put it near idt.c?
|
||||
global sys_exit_handler
|
||||
extern printf
|
||||
sys_exit_handler:
|
||||
; Сохраняем регистры Ring 3
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
; Переключаемся на сегменты Ring 0
|
||||
mov ax, 0x10 ; Селектор данных Ring 0 (gdt_data)
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
; Выполняем действие
|
||||
push sys_exit_msg
|
||||
call printf
|
||||
add esp, 4
|
||||
|
||||
; Восстанавливаем сегменты Ring 3
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
|
||||
; Возвращаемся в Ring 3
|
||||
iret
|
||||
|
||||
global test_user_function
|
||||
test_user_function:
|
||||
mov eax, 0xDEADBEEF
|
||||
int 0x80
|
||||
jmp $
|
||||
|
||||
section .data
|
||||
sys_exit_msg: db "Returned from Ring 3", 0
|
||||
+58
-4
@@ -107,14 +107,68 @@ void task2(int arg1, int arg2)
|
||||
while(1){printf("task2 %X %X\n", arg1, arg2);}
|
||||
}
|
||||
|
||||
void jump_usermode2(void);
|
||||
|
||||
void scheduler_init()
|
||||
{
|
||||
jump_usermode2();
|
||||
//we create this task two times because in other case it just won't start
|
||||
task_create((EntryPoint)&idle, NULL, 0);
|
||||
task_create((EntryPoint)&idle, NULL, 0);
|
||||
//task_create((EntryPoint)&idle, NULL, 0);
|
||||
//task_create((EntryPoint)&idle, NULL, 0);
|
||||
|
||||
void* args1[] = {(void*)42, (void*)"ebalo"};
|
||||
task_create((EntryPoint)&task1, args1, 2);
|
||||
//task_create((EntryPoint)&task1, args1, 2);
|
||||
void* args2[] = {(void*)69, (void*)420};
|
||||
task_create((EntryPoint)&task2, args2, 2);
|
||||
//task_create((EntryPoint)&task2, args2, 2);
|
||||
}
|
||||
|
||||
extern void test_user_function(void);
|
||||
void jump_usermode2(void) {
|
||||
void* code_phys = alloc_page();
|
||||
if (!code_phys) {
|
||||
printf("No memory for user code\n");
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Временно отображаем code_phys в ядре
|
||||
uint32_t kernel_temp_virt = 0xC0100000;
|
||||
map_page(code_phys, (void*)kernel_temp_virt, 0x3); // Present, R/W, Supervisor
|
||||
|
||||
// Копируем код
|
||||
uint32_t* src = (uint32_t*)test_user_function;
|
||||
uint32_t* dst = (uint32_t*)kernel_temp_virt;
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
printf("Copied code to 0x%x (virt 0x%x): 0x%x 0x%x 0x%x\n",
|
||||
(uint32_t)code_phys, kernel_temp_virt, dst[0], dst[1], dst[2]);
|
||||
|
||||
// Настраиваем Ring 3
|
||||
uint32_t user_stack_top;
|
||||
void* user_code_virt = setup_user_process(code_phys, &user_stack_top);
|
||||
if (!user_code_virt) {
|
||||
printf("Failed to setup user process\n");
|
||||
while (1);
|
||||
}
|
||||
|
||||
printf("user_code_virt: 0x%x, user_stack_top: 0x%x\n",
|
||||
(uint32_t)user_code_virt, user_stack_top);
|
||||
|
||||
asm volatile (
|
||||
"mov $0x23, %%dx\n"
|
||||
"mov %%dx, %%ds\n"
|
||||
"mov %%dx, %%es\n"
|
||||
"mov %%dx, %%fs\n"
|
||||
"mov %%dx, %%gs\n"
|
||||
"push $0x23\n"
|
||||
"push %0\n"
|
||||
"pushf\n"
|
||||
"push $0x1B\n"
|
||||
"push %1\n"
|
||||
"iret\n"
|
||||
:
|
||||
: "r" (user_stack_top), "r" (user_code_virt)
|
||||
: "dx", "memory"
|
||||
);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user