tasking: add simple base for running things in ring 3
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o \
|
OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o \
|
||||||
bin/utils.o bin/string.o bin/stdio.o bin/disk.o bin/pic.o bin/pit.o \
|
bin/utils.o bin/string.o bin/stdio.o bin/disk.o bin/pic.o bin/pit.o \
|
||||||
bin/keyboard.o bin/paging.o bin/heap.o bin/page_alloc.o bin/page_tables.o \
|
bin/keyboard.o bin/paging.o bin/heap.o bin/page_alloc.o bin/page_tables.o \
|
||||||
bin/fat.o bin/task.o bin/switch.o
|
bin/fat.o bin/task.o bin/switch.o bin/sys_exit.o
|
||||||
|
|
||||||
# Define the compiler and assembler
|
# Define the compiler and assembler
|
||||||
CC = gcc -D__is_katauos
|
CC = gcc -D__is_katauos
|
||||||
@@ -114,6 +114,9 @@ bin/switch.o: src/tasking/switch.asm
|
|||||||
bin/task.o: src/tasking/task.c
|
bin/task.o: src/tasking/task.c
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
bin/sys_exit.o: src/tasking/sys_exit.asm
|
||||||
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin/
|
rm -rf bin/
|
||||||
rm -f $(OUTPUT)
|
rm -f $(OUTPUT)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
extern uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
extern uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
||||||
extern uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
|
extern uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
|
||||||
|
extern uint32_t user_page_table[1024] __attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
|
||||||
//paging.c
|
//paging.c
|
||||||
@@ -24,6 +25,7 @@ void free_page(void* physaddr);
|
|||||||
void *get_physaddr(void *virtualaddr);
|
void *get_physaddr(void *virtualaddr);
|
||||||
void map_page(void* physaddr, void* virtualaddr, unsigned int flags);
|
void map_page(void* physaddr, void* virtualaddr, unsigned int flags);
|
||||||
void map_kernel_page(void* virtualaddr, unsigned int flags);
|
void map_kernel_page(void* virtualaddr, unsigned int flags);
|
||||||
|
void* setup_user_process(void* user_code_phys, uint32_t* user_stack_top);
|
||||||
|
|
||||||
//heap.c
|
//heap.c
|
||||||
void heap_init();
|
void heap_init();
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ __attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame);
|
|||||||
void isr_custom();
|
void isr_custom();
|
||||||
void default_handler();
|
void default_handler();
|
||||||
|
|
||||||
|
extern void sys_exit_handler();
|
||||||
|
|
||||||
void isr_install() {
|
void isr_install() {
|
||||||
idt_set_descriptor(0, (uint32)isr0, 0x8E);
|
idt_set_descriptor(0, (uint32)isr0, 0x8E);
|
||||||
idt_set_descriptor(1, (uint32)isr1, 0x8E);
|
idt_set_descriptor(1, (uint32)isr1, 0x8E);
|
||||||
@@ -62,6 +64,7 @@ void isr_install() {
|
|||||||
idt_set_descriptor(0x20, (uint32)isr_timer, 0x8E);
|
idt_set_descriptor(0x20, (uint32)isr_timer, 0x8E);
|
||||||
idt_set_descriptor(0x21, (uint32)isr_custom, 0x8E);
|
idt_set_descriptor(0x21, (uint32)isr_custom, 0x8E);
|
||||||
|
|
||||||
|
idt_set_descriptor(0x80, (uint32)sys_exit_handler, 0xEE);
|
||||||
|
|
||||||
idt_set(); // Load with ASM
|
idt_set(); // Load with ASM
|
||||||
printf("isr_install done\n");
|
printf("isr_install done\n");
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
#include "../include/paging.h"
|
#include "../include/paging.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static uint32_t next_user_virt = 0x00400000;
|
||||||
|
void* setup_user_process(void* user_code_phys, uint32_t* user_stack_top) {
|
||||||
|
void* stack_phys = alloc_page();
|
||||||
|
if (!stack_phys) return 0;
|
||||||
|
|
||||||
|
uint32_t code_virt = next_user_virt;
|
||||||
|
uint32_t stack_virt = code_virt + 0x3FF000; // 4 МБ - 4 КБ
|
||||||
|
map_page(user_code_phys, (void*)code_virt, 0x7);
|
||||||
|
map_page(stack_phys, (void*)stack_virt, 0x7);
|
||||||
|
|
||||||
|
*user_stack_top = stack_virt + 0x1000;
|
||||||
|
next_user_virt += 0x400000; // Следующий 4 МБ блок
|
||||||
|
return (void*)code_virt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_user_process(void* code_phys, void* stack_phys) {
|
||||||
|
free_page(code_phys);
|
||||||
|
free_page(stack_phys);
|
||||||
|
}
|
||||||
|
|
||||||
void *get_physaddr(void *virtualaddr) {
|
void *get_physaddr(void *virtualaddr) {
|
||||||
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
|
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
|
||||||
unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF;
|
unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF;
|
||||||
|
|||||||
+10
-1
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
||||||
uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
|
uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
|
||||||
|
uint32_t user_page_table[1024] __attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
|
||||||
void enablePaging() {
|
void enablePaging() {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
@@ -35,8 +37,9 @@ void paging_init() {
|
|||||||
// Проверяем физические адреса
|
// Проверяем физические адреса
|
||||||
uint32_t pd_phys = (uint32_t)kernel_page_directory;
|
uint32_t pd_phys = (uint32_t)kernel_page_directory;
|
||||||
uint32_t pt_phys = (uint32_t)kernel_page_table;
|
uint32_t pt_phys = (uint32_t)kernel_page_table;
|
||||||
|
uint32_t user_pt_phys = (uint32_t)user_page_table;
|
||||||
|
|
||||||
if (pd_phys & 0xFFF || pt_phys & 0xFFF) {
|
if (pd_phys & 0xFFF || pt_phys & 0xFFF || user_pt_phys & 0xFFF) {
|
||||||
while (1); // Ошибка выравнивания
|
while (1); // Ошибка выравнивания
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +54,12 @@ void paging_init() {
|
|||||||
}
|
}
|
||||||
kernel_page_directory[0] = pt_phys | 0x3;
|
kernel_page_directory[0] = pt_phys | 0x3;
|
||||||
|
|
||||||
|
// Ring 3: 0x00400000–0x007FFFFF, User-accessible
|
||||||
|
for (i = 0; i < 1024; i++) {
|
||||||
|
user_page_table[i] = 0; // Изначально не отображено
|
||||||
|
}
|
||||||
|
kernel_page_directory[1] = user_pt_phys | 0x7; // Present, R/W, User
|
||||||
|
|
||||||
// Рекурсивное отображение
|
// Рекурсивное отображение
|
||||||
kernel_page_directory[1023] = pd_phys | 0x3;
|
kernel_page_directory[1023] = pd_phys | 0x3;
|
||||||
|
|
||||||
|
|||||||
@@ -94,3 +94,24 @@ switchProcess:
|
|||||||
; |------------------------|
|
; |------------------------|
|
||||||
|
|
||||||
ret
|
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);}
|
while(1){printf("task2 %X %X\n", arg1, arg2);}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void jump_usermode2(void);
|
||||||
|
|
||||||
void scheduler_init()
|
void scheduler_init()
|
||||||
{
|
{
|
||||||
|
jump_usermode2();
|
||||||
//we create this task two times because in other case it just won't start
|
//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"};
|
void* args1[] = {(void*)42, (void*)"ebalo"};
|
||||||
task_create((EntryPoint)&task1, args1, 2);
|
//task_create((EntryPoint)&task1, args1, 2);
|
||||||
void* args2[] = {(void*)69, (void*)420};
|
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