hazel/kernel/kernel.c

206 lines
6.6 KiB
C
Raw Normal View History

2024-06-27 18:36:32 -04:00
#include <kernel/kernel.h>
2024-06-25 22:47:21 -04:00
#include <kernel/multiboot.h>
2024-07-02 18:44:36 -04:00
#include <kernel/mem.h>
2024-06-27 18:36:32 -04:00
#include <kernel/serial.h>
2024-07-01 19:28:45 -04:00
#include <kernel/idt.h>
#include <kernel/pic.h>
#include <kernel/pit.h>
2024-07-06 03:51:46 -04:00
#include <kernel/elf.h>
#include <kernel/task.h>
2024-07-28 10:11:15 -04:00
#include <kernel/ps2.h>
2024-07-03 21:55:44 -04:00
#include <stdint.h>
2024-06-27 18:36:32 -04:00
kernel_ctx_t ctx = {0};
2024-07-01 19:28:45 -04:00
struct idt_entry idt[256] = {0};
struct idtr idtr = {0};
2024-07-03 21:55:44 -04:00
tss_t tss = {0};
2024-07-01 19:28:45 -04:00
extern uint32_t isr_stub_table[32];
extern void pit_isr(void);
2024-07-28 10:11:15 -04:00
extern void ps2_isr(void);
2024-07-03 12:17:32 -04:00
extern void jmp_user_mode(uint32_t esp, uint32_t eip);
2024-07-03 21:55:44 -04:00
extern void flush_tss(uint32_t segment_selector);
2024-07-06 18:00:06 -04:00
extern void task_switch(task_t *task);
2024-07-15 14:03:44 -04:00
extern void syscall(void);
extern void syscall_isr(void);
2024-07-03 21:55:44 -04:00
extern gdt_t gdt[6];
extern uint32_t boot_page_dir[1024];
extern uint32_t boot_page_tab[1024];
2024-07-01 19:28:45 -04:00
2024-07-28 10:11:15 -04:00
#define FD_STDIN 0
#define FD_STDOUT 1
2024-07-15 14:03:44 -04:00
void syscall_write(stack_frame_t r) {
2024-07-28 10:11:15 -04:00
uint32_t fd = r.edi;
uint8_t *buf = (uint8_t *)r.esi;
if (fd == FD_STDOUT) {
2024-07-28 10:18:59 -04:00
LOG("%s", buf);
2024-07-28 10:11:15 -04:00
}
}
void syscall_read(stack_frame_t r) {
uint32_t fd = r.edi;
uint8_t *buf = (uint8_t *)r.esi;
uint32_t len = r.edx;
if (fd == FD_STDOUT) {
2024-07-28 10:18:59 -04:00
// Not yet
2024-07-28 10:11:15 -04:00
} else if (fd == FD_STDIN) {
// for some reason interrupts are disabled
2024-07-28 10:18:59 -04:00
asm volatile ("sti" ::);
while (ctx.current_task->stdin[ctx.current_task->stdin_len - 1] != '\n') cpu_relax;
if (ctx.current_task->stdin_len > 0) ctx.current_task->stdin[--ctx.current_task->stdin_len] = 0;
memcpy(buf, ctx.current_task->stdin, len);
for (int i = 0; i < 0x1000; i++) ctx.current_task->stdin[i] = 0;
ctx.current_task->stdin_len = 0;
2024-07-28 10:11:15 -04:00
}
}
void syscall_reboot(stack_frame_t r) {
(void)r;
ps2_reboot;
}
2024-07-28 10:11:15 -04:00
void syscall_uptime(stack_frame_t r) {
uint64_t *buf = (uint64_t *)r.esi;
*buf = ctx.ticks;
2024-07-15 14:03:44 -04:00
}
2024-07-01 19:28:45 -04:00
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);
LOG("\nEIP: 0x%08X\nCS: 0x%08X\nEFLAGS: 0x%08X\n",
r.eip, r.cs, r.eflags);
2024-07-07 23:42:44 -04:00
for (;;) {}
2024-07-01 19:28:45 -04:00
}
2024-06-25 22:47:21 -04:00
2024-07-02 00:46:29 -04:00
void sleep(int delay) {
uint64_t end = ctx.ticks + delay;
while (ctx.ticks < end)
2024-07-28 10:18:59 -04:00
cpu_relax;
2024-07-02 00:46:29 -04:00
}
2024-07-06 18:00:06 -04:00
void idt_init(void) {
2024-07-06 03:51:46 -04:00
for (int i = 0; i < 32; i++) {
idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
}
2024-07-28 10:11:15 -04:00
idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
idt_encode_entry(idt, 0x21, (uint32_t)ps2_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
idt_encode_entry(idt, 0x80, (uint32_t)syscall_isr, GDT_SEGMENT_SELECTOR(GDT_USER_CODE, RING3), TRAP_GATE_32 | INT_RING3 | INT_PRESENT);
2024-07-28 10:18:59 -04:00
2024-07-06 03:51:46 -04:00
idtr.size = (sizeof(struct idt_entry) * 256) - 1;
idtr.base = (uint32_t) idt;
asm volatile ("lidt %0" :: "m"(idtr));
}
2024-07-04 23:44:13 -04:00
2024-06-25 22:47:21 -04:00
void kernel(multiboot_info_t *info) {
2024-07-06 03:51:46 -04:00
if (!CHECK_FLAG(info->flags, 3)) goto halt; // Modules
2024-07-28 10:11:15 -04:00
if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map
if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data
2024-06-27 18:36:32 -04:00
2024-06-30 21:27:33 -04:00
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
2024-06-27 18:36:32 -04:00
LOG("Kernel log being sent to COM1\n");
2024-07-01 19:28:45 -04:00
2024-07-06 03:51:46 -04:00
ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA);
ctx.multi_mmap_size = info->memmaplength;
2024-07-02 18:44:36 -04:00
if (!mmap_init()) goto halt;
2024-07-03 11:23:21 -04:00
LOG("%d bytes of RAM detected\nCreated a %d byte large physical memory map at 0x%08X\n", ctx.mmap_size*BLOCK_SIZE*8, ctx.mmap_size, (uint32_t)ctx.mmap);
2024-07-02 18:44:36 -04:00
2024-07-06 03:51:46 -04:00
idt_init();
2024-07-07 23:42:44 -04:00
2024-07-01 19:28:45 -04:00
pic_remap(PIC_1_START, PIC_2_START);
2024-07-28 10:11:15 -04:00
ps2_init();
2024-07-06 03:51:46 -04:00
asm volatile ("sti" ::);
ctx.ticks = 0;
pit_init();
2024-07-07 23:42:44 -04:00
2024-07-06 03:51:46 -04:00
// Setup TSS
2024-07-03 21:55:44 -04:00
uint32_t base = (uint32_t)&tss;
uint32_t limit = base + sizeof(tss_t);
gdt[5].base_low = base & 0xFFFF;
gdt[5].base_middle = (base >> 16) & 0xFF;
gdt[5].base_high = (base >> 24) & 0xFF;
gdt[5].limit_low = limit & 0xFFFF;
gdt[5].granularity = (limit >> 16) & 0x0F;
gdt[5].granularity |= 0x40;
gdt[5].access = 0x89;
2024-07-06 03:51:46 -04:00
tss.ss0 = GDT_SEGMENT_SELECTOR(GDT_KERNEL_DATA, RING0);
2024-07-04 23:44:13 -04:00
uint32_t esp0 = 0;
asm volatile ("mov %%esp, %0" : "=r" (esp0));
2024-07-28 10:11:15 -04:00
// Questionable
2024-07-04 23:44:13 -04:00
tss.esp0 = esp0;
2024-07-06 03:51:46 -04:00
tss.cs = GDT_SEGMENT_SELECTOR(GDT_USER_CODE, RING3);
tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(GDT_USER_DATA, RING3);
2024-07-03 21:55:44 -04:00
flush_tss(GDT_SEGMENT_SELECTOR(5, RING3));
2024-07-15 14:03:44 -04:00
/*
2024-07-28 10:18:59 -04:00
task_t task1 = {0};
task_t task2 = {0};
task1.cr3 = (uint32_t)boot_page_dir - KERNEL_VMA;
task1.next = (uint32_t *)&task2;
ctx.current_task = &task1;
uint32_t *stack = mmap_find_first_free_block();
asm volatile ("mov %%esp, %0" : "=r" (task1.esp));
stack[1023] = 0x207;
stack[1022] = 0x8;
stack[1021] = (uint32_t)test;
stack[1020] = 0xDEADBEEF;
stack[1019] = 0xDEADBEEF;
stack[1018] = 0xDEADBEEF;
stack[1017] = 0xDEADBEEF;
stack[1016] = 0xDEADBEEF;
stack[1015] = 0xDEADBEEF;
stack[1014] = 0xDEADBEEF;
stack[1013] = 0xDEADBEEF;
task2.esp = (uint32_t)stack + (0x1000 - 44);
task2.cr3 = (uint32_t)boot_page_dir - KERNEL_VMA;
task2.next = 0;
*/
2024-07-07 23:42:44 -04:00
multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA);
elf_t *elf = (elf_t *)(init->mod_start+KERNEL_VMA);
2024-07-06 03:51:46 -04:00
task_t task = {0};
if (!task_init(&task, elf)) goto halt;
2024-07-03 21:55:44 -04:00
2024-07-06 03:51:46 -04:00
ctx.current_task = &task;
asm volatile ("mov %0, %%cr3" :: "r"(task.cr3));
2024-07-03 21:55:44 -04:00
2024-07-15 14:03:44 -04:00
// Set the ring0 CS
asm volatile (
2024-07-28 10:18:59 -04:00
"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"
);
2024-07-15 14:03:44 -04:00
// Set the ring0 stack
uint32_t *k_stack = mmap_find_first_free_block();
asm volatile (
2024-07-28 10:18:59 -04:00
"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"
);
2024-07-15 14:03:44 -04:00
// Set the ring0 syscall entry
asm volatile (
2024-07-28 10:18:59 -04:00
"movl $0x176, %%ecx \n\t"
"movl %0, %%eax \n\t"
"xor %%edx, %%edx \n\t"
"wrmsr"
:
: "r"(syscall)
: "eax", "ecx", "edx"
);
2024-07-15 14:03:44 -04:00
2024-07-06 03:51:46 -04:00
LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", task.eip, task.esp);
jmp_user_mode(task.esp, task.eip);
2024-07-02 00:46:29 -04:00
2024-06-27 18:36:32 -04:00
halt:
2024-06-25 15:28:44 -04:00
for (;;) {}
}