diff --git a/include/task.h b/include/task.h index 33930d1..d06f240 100644 --- a/include/task.h +++ b/include/task.h @@ -4,10 +4,10 @@ #include // Сегменты для ядра и пользователя -#define SEG_KCODE 1 // Сегмент кода ядра -#define SEG_KDATA 2 // Сегмент данных ядра -#define SEG_UCODE 3 // Сегмент кода пользователя -#define SEG_UDATA 4 // Сегмент данных пользователя +#define SEG_KCODE 0x08 // Сегмент кода ядра +#define SEG_KDATA 0x10 // Сегмент данных ядра +#define SEG_UCODE 0x18 // Сегмент кода пользователя +#define SEG_UDATA 0x20 // Сегмент данных пользователя #define DPL_KERNEL 0 // Уровень привилегий ring 0 #define DPL_USER 3 // Уровень привилегий ring 3 @@ -25,7 +25,7 @@ typedef enum TaskState typedef void (*EntryPoint)(void); // Структура контекста для переключения между процессами -typedef struct Context { +typedef struct __attribute__((packed)) Context { uint32_t edi; uint32_t esi; uint32_t ebx; @@ -34,7 +34,7 @@ typedef struct Context { } Context; // Структура trap frame для перехода в ring 3 -typedef struct TrapFrame { +typedef struct __attribute__((packed)) TrapFrame { uint32_t edi; uint32_t esi; uint32_t ebp; diff --git a/src/tasking/sys_exit.asm b/src/tasking/sys_exit.asm index 2376554..3234153 100644 --- a/src/tasking/sys_exit.asm +++ b/src/tasking/sys_exit.asm @@ -33,9 +33,17 @@ sys_exit_handler: global test_user_function test_user_function: +nigg: mov eax, 0xB00B1E5 ; 0xDEADBEEF int 0x80 - jmp $ + jmp nigg + +global second_user_function +second_user_function: +heh: + mov eax, 0xFACE5EA7 + int 0x80 + jmp heh section .data sys_exit_msg: db "Returned from Ring 3", 0 diff --git a/src/tasking/task.c b/src/tasking/task.c index a206469..c6c9782 100644 --- a/src/tasking/task.c +++ b/src/tasking/task.c @@ -41,6 +41,10 @@ Process* task_create(EntryPoint func, void** args, uint32_t arg_count, uint32_t uint32_t* sp = (uint32_t*)(p->kstack + KSTACKSIZE); if (ring == DPL_USER) { + + void* user_stack = alloc_page(); + map_page(user_stack, (void*)0x800000, 0x7); // U/S=1, R/W=1 + // Настраиваем trap frame для ring 3 sp -= sizeof(TrapFrame) / 4; p->tf = (TrapFrame*)sp; @@ -52,14 +56,16 @@ Process* task_create(EntryPoint func, void** args, uint32_t arg_count, uint32_t p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->eip = (uint32_t)func; - p->tf->esp = USTACKSIZE; // Предполагаем, что пользовательский стек настроен + p->tf->esp = 0x800000 + USTACKSIZE; // Предполагаем, что пользовательский стек настроен // Добавляем адрес возврата для trapret sp -= 1; *sp = (uint32_t)trapret; } else { - // Для ring 0 не используем trap frame - p->tf = NULL; + p->tf = NULL; // Для ring 0 TrapFrame не нужен! + sp -= sizeof(Context) / 4; // Только контекст + p->context = (Context*)sp; + p->context->eip = (uint32_t)func; // Прямой переход в func } // Настраиваем начальный контекст sp -= 5; // Место для edi, esi, ebx, ebp, eip @@ -142,19 +148,21 @@ void jump_usermode2(void) ; void scheduler_init() { - task_create((EntryPoint)idle, NULL, 0, 0); - task_create((EntryPoint)idle, NULL, 0, 0); + task_create((EntryPoint)&idle, NULL, 0, 0); + task_create((EntryPoint)&idle, NULL, 0, 0); void* args1[] = {(void*)42, (void*)"ebalo"}; - task_create((EntryPoint)task1, args1, 2, 0); + task_create((EntryPoint)&task1, args1, 2, 0); void* args2[] = {(void*)69, (void*)420}; - task_create((EntryPoint)task2, args2, 2, 0); + task_create((EntryPoint)&task2, args2, 2, 0); jump_usermode2(); } #include "../include/string.h" extern void test_user_function(void); +extern void second_user_function(void); + void jump_usermode2(void) { void* code_phys = alloc_page(); if (!code_phys) { @@ -162,12 +170,17 @@ void jump_usermode2(void) { while (1); } + void *second_code_phys = alloc_page(); + // Temporarily map code_phys into kernel space uint32_t kernel_temp_virt = 0xC0500000; + uint32_t kernel_temp_virt2 = 0xC0600000; map_page(code_phys, (void*)kernel_temp_virt, 0x3); // R/W in kernel + map_page(second_code_phys, (void*)kernel_temp_virt2, 0x3); // R/W in kernel // Copy user code memcpy((void*)kernel_temp_virt, test_user_function, 4096); // Use memcpy + memcpy((void*)kernel_temp_virt2, second_user_function, 4096); // Use memcpy printf("Copied code at 0x%x: 0x%x 0x%x 0x%x\n", kernel_temp_virt, @@ -177,6 +190,7 @@ void jump_usermode2(void) { // Unmap temporary kernel mapping unmap_page((void*)kernel_temp_virt); + unmap_page((void*)kernel_temp_virt2); printf("Copied code to 0x%x (virt 0x%x)\n", @@ -184,17 +198,21 @@ void jump_usermode2(void) { // Настраиваем Ring 3 uint32_t user_stack_top; + uint32_t user_stack_top2; 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); } + void *second_user_code_virt = setup_user_process(second_code_phys, &user_stack_top2); + printf("user_code_virt: 0x%x, user_stack_top: 0x%x\n", (uint32_t)user_code_virt, user_stack_top); //map_page(alloc_page(), (void*)0x400000, 0x7); map_page(alloc_page(), (void*)0x800000, 0x7); + map_page(alloc_page(), (void*)0x900000, 0x7); uint32_t code_pte = get_pte(user_code_virt); printf("Before iret: Code PTE at 0x%x: 0x%x (phys 0x%x, %s, %s)\n", @@ -203,7 +221,9 @@ void jump_usermode2(void) { (code_pte & 0x4) ? "user" : "supervisor"); task_create(user_code_virt, NULL, 0, 3); + //task_create(second_user_code_virt, NULL, 0, 3); + return; // Switch to user mode with interrupts enabled asm volatile ( "pushf\n"