diff --git a/Makefile b/Makefile index cef82d6..f46ee64 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ ISO := Hazel.iso CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) \ - -s \ + -s -d int \ -m 512M \ -serial stdio diff --git a/boot/initrd b/boot/initrd index 11500d7..c533958 100644 Binary files a/boot/initrd and b/boot/initrd differ diff --git a/include/kernel/idt.h b/include/kernel/idt.h index c6e3655..168742c 100644 --- a/include/kernel/idt.h +++ b/include/kernel/idt.h @@ -45,6 +45,10 @@ typedef struct { uint32_t eflags; } int_stack_frame_t; +typedef struct { + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */ +} stack_frame_t; + void idt_encode_entry(struct idt_entry idt[], int i, uint32_t offset, uint16_t segment_selector, uint8_t attributes); #endif diff --git a/include/kernel/task.h b/include/kernel/task.h index 74b7d86..b6bcd2b 100644 --- a/include/kernel/task.h +++ b/include/kernel/task.h @@ -8,6 +8,7 @@ typedef struct { uint32_t esp; uint32_t cr3; uint32_t *next; + uint32_t eip; } task_t; int task_init(task_t *task, elf_t *elf); diff --git a/kernel/init.asm b/kernel/init.asm index da11ca4..abcd613 100644 --- a/kernel/init.asm +++ b/kernel/init.asm @@ -94,7 +94,8 @@ pit_isr: extern pit_handler call pit_handler cmp eax, 1 - jne .ret + ; jne .ret + jmp .ret mov edi, [ctx+28] ; EDI = current task ; mov esi, [edi+8] ; ESI = next task @@ -133,6 +134,25 @@ flush_tss: ltr [esp+4] ret +global syscall_isr +syscall_isr: + pushad + mov ecx, esp + sysenter +after_syscall: + popad + iret + +global syscall +syscall: + imul eax, eax, 4 + add eax, syscall_table + pushad + call [eax] + popad + mov edx, after_syscall + sysexit + extern exception_handler %macro isr_err_stub 1 isr_stub_%+%1: @@ -247,6 +267,13 @@ global boot_page_tab align 0x1000 boot_page_tab: times 1024 dd 0 +global syscall_table +syscall_table: + dd 0 + + extern syscall_write + dd syscall_write + section .bss align 16 stack_top: diff --git a/kernel/kernel.c b/kernel/kernel.c index f0be75d..49651ff 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -19,10 +19,16 @@ extern void pit_isr(void); extern void jmp_user_mode(uint32_t esp, uint32_t eip); extern void flush_tss(uint32_t segment_selector); extern void task_switch(task_t *task); +extern void syscall(void); +extern void syscall_isr(void); extern gdt_t gdt[6]; extern uint32_t boot_page_dir[1024]; extern uint32_t boot_page_tab[1024]; +void syscall_write(stack_frame_t r) { + LOG("SYSCALL %08X\n", r.eax); +} + void exception_handler(int_stack_frame_t r) { LOG("Exception 0x%X (0x%X) has occurred\nEAX: 0x%08X\nECX: 0x%08X\nEDX: 0x%08X\nEBX: 0x%08X\nESI: 0x%08X\nEDI: 0x%08X\nEBP: 0x%08X\nESP: 0x%08X\n", r.int_no, r.err_code, r.eax, r.ecx, r.edx, r.ebx, r.esi, r.edi, r.ebp, r.esp+24); @@ -42,6 +48,7 @@ void idt_init(void) { idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT); } idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), INT_GATE_32 | INT_RING0 | INT_PRESENT); + idt_encode_entry(idt, 0x80, (uint32_t)syscall_isr, GDT_SEGMENT_SELECTOR(GDT_USER_CODE, RING3), INT_GATE_32 | INT_RING3 | INT_PRESENT); idtr.size = (sizeof(struct idt_entry) * 256) - 1; idtr.base = (uint32_t) idt; @@ -51,7 +58,7 @@ void idt_init(void) { void test(void) { for (;;) { - LOG("B"); + LOG("B"); } } @@ -93,6 +100,7 @@ void kernel(multiboot_info_t *info) { tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(GDT_USER_DATA, RING3); flush_tss(GDT_SEGMENT_SELECTOR(5, RING3)); + /* task_t task1 = {0}; task_t task2 = {0}; task1.cr3 = (uint32_t)boot_page_dir - KERNEL_VMA; @@ -115,12 +123,8 @@ void kernel(multiboot_info_t *info) { task2.esp = (uint32_t)stack + (0x1000 - 44); task2.cr3 = (uint32_t)boot_page_dir - KERNEL_VMA; task2.next = 0; + */ - for (;;) { - LOG("A"); - } - - /* multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA); elf_t *elf = (elf_t *)(init->mod_start+KERNEL_VMA); task_t task = {0}; @@ -129,9 +133,41 @@ void kernel(multiboot_info_t *info) { ctx.current_task = &task; asm volatile ("mov %0, %%cr3" :: "r"(task.cr3)); + // Set the ring0 CS + asm volatile ( + "movl $0x174, %%ecx \n\t" + "movl %0, %%eax \n\t" + "xor %%edx, %%edx \n\t" + "wrmsr" + : + : "r"(GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0)) + : "eax", "ecx", "edx" + ); + // Set the ring0 stack + uint32_t *k_stack = mmap_find_first_free_block(); + asm volatile ( + "movl $0x175, %%ecx \n\t" + "movl %0, %%eax \n\t" + "xor %%edx, %%edx \n\t" + "wrmsr" + : + : "r"((uint32_t)k_stack + 0x1000) + : "eax", "ecx", "edx" + ); + // Set the ring0 syscall entry + asm volatile ( + "movl $0x176, %%ecx \n\t" // MSR address + "movl %0, %%eax \n\t" // Lower 32 bits (eip) + "xor %%edx, %%edx \n\t" // Upper 32 bits (zero for 32-bit value) + "wrmsr" + : + : "r"(syscall) + : "eax", "ecx", "edx" + ); + + LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", task.eip, task.esp); jmp_user_mode(task.esp, task.eip); - */ halt: for (;;) {} diff --git a/kernel/task.c b/kernel/task.c index 1f647c8..a46528e 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -7,7 +7,7 @@ extern kernel_ctx_t ctx; int task_init(task_t *task, elf_t *elf) { section_t *text = elf_find_section(elf, ".text"); if (!text) return 0; - //task->eip = elf->e_entry + text->sh_offset; + task->eip = elf->e_entry + text->sh_offset; // Allocate a page for a stack task->esp = (uint32_t)mmap_find_first_free_block() + 0x1000; @@ -16,7 +16,7 @@ int task_init(task_t *task, elf_t *elf) { uint32_t *page_tab = mmap_find_first_free_block(); for (int i = 0; i < 1024; i++) { // Map kernel to 3GiB - if (i == 768) page_dir[i] = ((uint32_t)boot_page_tab - KERNEL_VMA) | 3; + if (i == 768) page_dir[i] = ((uint32_t)boot_page_tab - KERNEL_VMA) | 7; // Map 3.4GiB-4GiB as non-present kernel entries else if (i > 768) page_dir[i] = 4; // Map remaining entries as non-present u/s diff --git a/user/userinit.asm b/user/userinit.asm index 58290f9..f7f0ae9 100644 --- a/user/userinit.asm +++ b/user/userinit.asm @@ -1,5 +1,7 @@ [bits 32] global _start _start: - mov eax, 0xDEADBEEF + mov ecx, 0xDEADBEEF + mov eax, 1 + int 0x80 jmp $