working on task switching
This commit is contained in:
parent
766596ef98
commit
1b7474095b
46
include/kernel/elf.h
Normal file
46
include/kernel/elf.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef HAZEL_ELF_H_
|
||||||
|
#define HAZEL_ELF_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
|
||||||
|
typedef uint16_t Elf32_Half;
|
||||||
|
typedef uint32_t Elf32_Addr;
|
||||||
|
typedef uint32_t Elf32_Off;
|
||||||
|
typedef uint32_t Elf32_Word;
|
||||||
|
typedef int32_t Elf32_Sword;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t e_ident[EI_NIDENT];
|
||||||
|
Elf32_Half e_type;
|
||||||
|
Elf32_Half e_machine;
|
||||||
|
Elf32_Word e_version;
|
||||||
|
Elf32_Addr e_entry;
|
||||||
|
Elf32_Off e_phoff;
|
||||||
|
Elf32_Off e_shoff;
|
||||||
|
Elf32_Word e_flags;
|
||||||
|
Elf32_Half e_ehsize;
|
||||||
|
Elf32_Half e_phentsize;
|
||||||
|
Elf32_Half e_phnum;
|
||||||
|
Elf32_Half e_shentsize;
|
||||||
|
Elf32_Half e_shnum;
|
||||||
|
Elf32_Half e_shstrndx;
|
||||||
|
} elf_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Word sh_name;
|
||||||
|
Elf32_Word sh_type;
|
||||||
|
Elf32_Word sh_flags;
|
||||||
|
Elf32_Addr sh_addr;
|
||||||
|
Elf32_Off sh_offset;
|
||||||
|
Elf32_Word sh_size;
|
||||||
|
Elf32_Word sh_link;
|
||||||
|
Elf32_Word sh_info;
|
||||||
|
Elf32_Word sh_addralign;
|
||||||
|
Elf32_Word sh_entsize;
|
||||||
|
} section_t;
|
||||||
|
|
||||||
|
section_t *elf_find_section(elf_t *elf, const char *name);
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,16 +3,11 @@
|
||||||
|
|
||||||
#include <kernel/multiboot.h>
|
#include <kernel/multiboot.h>
|
||||||
#include <kernel/log.h>
|
#include <kernel/log.h>
|
||||||
|
#include <kernel/task.h>
|
||||||
|
|
||||||
#define cpu_relax asm volatile ("pause" ::)
|
#define cpu_relax asm volatile ("pause" ::)
|
||||||
#define CHECK_FLAG(x, n) (x & (1<<n))
|
#define CHECK_FLAG(x, n) (x & (1<<n))
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t eip;
|
|
||||||
uint32_t esp;
|
|
||||||
uint32_t cr3;
|
|
||||||
} task_t;
|
|
||||||
|
|
||||||
#define KERNEL_VMA 0xC0000000
|
#define KERNEL_VMA 0xC0000000
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -22,6 +17,7 @@ typedef struct {
|
||||||
uint32_t mmap_size;
|
uint32_t mmap_size;
|
||||||
log_method_t log_method;
|
log_method_t log_method;
|
||||||
uint64_t ticks;
|
uint64_t ticks;
|
||||||
|
task_t *current_task;
|
||||||
} kernel_ctx_t;
|
} kernel_ctx_t;
|
||||||
|
|
||||||
#define GDT_NULL 0
|
#define GDT_NULL 0
|
||||||
|
@ -84,42 +80,4 @@ struct tss_entry {
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
typedef struct tss_entry tss_t;
|
typedef struct tss_entry tss_t;
|
||||||
|
|
||||||
#define EI_NIDENT 16
|
|
||||||
|
|
||||||
typedef uint16_t Elf32_Half;
|
|
||||||
typedef uint32_t Elf32_Addr;
|
|
||||||
typedef uint32_t Elf32_Off;
|
|
||||||
typedef uint32_t Elf32_Word;
|
|
||||||
typedef int32_t Elf32_Sword;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t e_ident[EI_NIDENT];
|
|
||||||
Elf32_Half e_type;
|
|
||||||
Elf32_Half e_machine;
|
|
||||||
Elf32_Word e_version;
|
|
||||||
Elf32_Addr e_entry;
|
|
||||||
Elf32_Off e_phoff;
|
|
||||||
Elf32_Off e_shoff;
|
|
||||||
Elf32_Word e_flags;
|
|
||||||
Elf32_Half e_ehsize;
|
|
||||||
Elf32_Half e_phentsize;
|
|
||||||
Elf32_Half e_phnum;
|
|
||||||
Elf32_Half e_shentsize;
|
|
||||||
Elf32_Half e_shnum;
|
|
||||||
Elf32_Half e_shstrndx;
|
|
||||||
} elf_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Elf32_Word sh_name;
|
|
||||||
Elf32_Word sh_type;
|
|
||||||
Elf32_Word sh_flags;
|
|
||||||
Elf32_Addr sh_addr;
|
|
||||||
Elf32_Off sh_offset;
|
|
||||||
Elf32_Word sh_size;
|
|
||||||
Elf32_Word sh_link;
|
|
||||||
Elf32_Word sh_info;
|
|
||||||
Elf32_Word sh_addralign;
|
|
||||||
Elf32_Word sh_entsize;
|
|
||||||
} section_t;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
17
include/kernel/task.h
Normal file
17
include/kernel/task.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef HAZEL_TASK_H_
|
||||||
|
#define HAZEL_TASK_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <kernel/elf.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t *next;
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
int task_init(task_t *task, elf_t *elf);
|
||||||
|
void schedule(void);
|
||||||
|
|
||||||
|
#endif
|
16
kernel/elf.c
Normal file
16
kernel/elf.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <kernel/elf.h>
|
||||||
|
#include <strcmp.h>
|
||||||
|
|
||||||
|
section_t *elf_find_section(elf_t *elf, const char *name) {
|
||||||
|
section_t *str = (section_t *)((uint32_t)elf + elf->e_shoff + elf->e_shstrndx*elf->e_shentsize);
|
||||||
|
section_t *found = 0;
|
||||||
|
for (int i = 0; i < elf->e_shnum; i++) {
|
||||||
|
section_t *sec = (section_t *)((uint32_t)elf + elf->e_shoff + i*elf->e_shentsize);
|
||||||
|
const char *n = (char *)((uint32_t)elf + str->sh_offset + sec->sh_name);
|
||||||
|
if (!strcmp(n, name)) {
|
||||||
|
found = sec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
|
@ -115,6 +115,31 @@ flush_tss:
|
||||||
ltr [esp+4]
|
ltr [esp+4]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
extern ctx
|
||||||
|
global task_switch
|
||||||
|
task_switch:
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
push ebp
|
||||||
|
|
||||||
|
mov esi, [ctx+28]
|
||||||
|
; Return if only one process is running
|
||||||
|
mov eax, [esi+12]
|
||||||
|
cmp eax, 0
|
||||||
|
je ret
|
||||||
|
; Check if using same virtual memory
|
||||||
|
cmp [esi+8], [eax+8]
|
||||||
|
je .ret
|
||||||
|
mov ecx, [eax+8]
|
||||||
|
mov cr3, ecx
|
||||||
|
.ret:
|
||||||
|
pop ebp
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
extern exception_handler
|
extern exception_handler
|
||||||
%macro isr_err_stub 1
|
%macro isr_err_stub 1
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <kernel/idt.h>
|
#include <kernel/idt.h>
|
||||||
#include <kernel/pic.h>
|
#include <kernel/pic.h>
|
||||||
#include <kernel/pit.h>
|
#include <kernel/pit.h>
|
||||||
|
#include <kernel/elf.h>
|
||||||
|
#include <kernel/task.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
kernel_ctx_t ctx = {0};
|
kernel_ctx_t ctx = {0};
|
||||||
|
@ -33,42 +35,41 @@ void sleep(int delay) {
|
||||||
cpu_relax;
|
cpu_relax;
|
||||||
}
|
}
|
||||||
|
|
||||||
int strcmp(const char *str1, const char *str2) {
|
void idt_init() {
|
||||||
while (*str1 && (*str1 == *str2)) {
|
for (int i = 0; i < 32; i++) {
|
||||||
str1++;
|
idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
|
||||||
str2++;
|
|
||||||
}
|
}
|
||||||
return *(uint8_t *)str1 - *(uint8_t *)str2;
|
idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), INT_GATE_32 | INT_RING0 | INT_PRESENT);
|
||||||
|
|
||||||
|
idtr.size = (sizeof(struct idt_entry) * 256) - 1;
|
||||||
|
idtr.base = (uint32_t) idt;
|
||||||
|
|
||||||
|
asm volatile ("lidt %0" :: "m"(idtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void kernel(multiboot_info_t *info) {
|
void kernel(multiboot_info_t *info) {
|
||||||
if (!CHECK_FLAG(info->flags, 3)) goto halt; // Modules
|
if (!CHECK_FLAG(info->flags, 3)) goto halt; // Modules
|
||||||
if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map
|
if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map
|
||||||
if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data
|
if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data
|
||||||
ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA);
|
|
||||||
ctx.multi_mmap_size = info->memmaplength;
|
|
||||||
|
|
||||||
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
|
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
|
||||||
LOG("Kernel log being sent to COM1\n");
|
LOG("Kernel log being sent to COM1\n");
|
||||||
|
|
||||||
|
ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA);
|
||||||
|
ctx.multi_mmap_size = info->memmaplength;
|
||||||
if (!mmap_init()) goto halt;
|
if (!mmap_init()) goto halt;
|
||||||
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);
|
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);
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
idt_init();
|
||||||
idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
|
|
||||||
}
|
|
||||||
idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(1, 0), INT_GATE_32 | INT_RING0 | INT_PRESENT);
|
|
||||||
|
|
||||||
idtr.size = (sizeof(struct idt_entry) * 256) - 1;
|
/*
|
||||||
idtr.base = (uint32_t) idt;
|
|
||||||
|
|
||||||
asm volatile ("lidt %0" :: "m"(idtr));
|
|
||||||
pic_remap(PIC_1_START, PIC_2_START);
|
pic_remap(PIC_1_START, PIC_2_START);
|
||||||
//asm volatile ("sti" ::);
|
asm volatile ("sti" ::);
|
||||||
|
ctx.ticks = 0;
|
||||||
//ctx.ticks = 0;
|
pit_init();
|
||||||
//pit_init();
|
*/
|
||||||
|
|
||||||
|
// Setup TSS
|
||||||
uint32_t base = (uint32_t)&tss;
|
uint32_t base = (uint32_t)&tss;
|
||||||
uint32_t limit = base + sizeof(tss_t);
|
uint32_t limit = base + sizeof(tss_t);
|
||||||
gdt[5].base_low = base & 0xFFFF;
|
gdt[5].base_low = base & 0xFFFF;
|
||||||
|
@ -78,42 +79,24 @@ void kernel(multiboot_info_t *info) {
|
||||||
gdt[5].granularity = (limit >> 16) & 0x0F;
|
gdt[5].granularity = (limit >> 16) & 0x0F;
|
||||||
gdt[5].granularity |= 0x40;
|
gdt[5].granularity |= 0x40;
|
||||||
gdt[5].access = 0x89;
|
gdt[5].access = 0x89;
|
||||||
tss.ss0 = GDT_SEGMENT_SELECTOR(2, RING0);
|
tss.ss0 = GDT_SEGMENT_SELECTOR(GDT_KERNEL_DATA, RING0);
|
||||||
uint32_t esp0 = 0;
|
uint32_t esp0 = 0;
|
||||||
asm volatile ("mov %%esp, %0" : "=r" (esp0));
|
asm volatile ("mov %%esp, %0" : "=r" (esp0));
|
||||||
tss.esp0 = esp0;
|
tss.esp0 = esp0;
|
||||||
tss.cs = GDT_SEGMENT_SELECTOR(3, RING3);
|
tss.cs = GDT_SEGMENT_SELECTOR(GDT_USER_CODE, RING3);
|
||||||
tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(4, RING3);
|
tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(GDT_USER_DATA, RING3);
|
||||||
flush_tss(GDT_SEGMENT_SELECTOR(5, RING3));
|
flush_tss(GDT_SEGMENT_SELECTOR(5, RING3));
|
||||||
|
|
||||||
multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA);
|
multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA);
|
||||||
elf_t *elf = (elf_t *)(init->mod_start+KERNEL_VMA);
|
elf_t *elf = (elf_t *)(init->mod_start+KERNEL_VMA);
|
||||||
section_t *str = (section_t *)((uint32_t)elf + elf->e_shoff + elf->e_shstrndx*elf->e_shentsize);
|
task_t task = {0};
|
||||||
section_t *text = 0;
|
if (!task_init(&task, elf)) goto halt;
|
||||||
for (int i = 0; i < elf->e_shnum; i++) {
|
|
||||||
section_t *sec = (section_t *)((uint32_t)elf + elf->e_shoff + i*elf->e_shentsize);
|
|
||||||
//LOG("Pingas: %d\n", elf->e_shstrndx);
|
|
||||||
const char *name = (char *)((uint32_t)elf + str->sh_offset + sec->sh_name);
|
|
||||||
if (!strcmp(name, ".text")) {
|
|
||||||
text = sec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t elf_phys = (uint32_t)elf - KERNEL_VMA;
|
ctx.current_task = &task;
|
||||||
LOG("0x%08X\n", elf_phys);
|
asm volatile ("mov %0, %%cr3" :: "r"(task.cr3));
|
||||||
uint32_t *elf_page_dir = mmap_find_first_free_block();
|
|
||||||
uint32_t *elf_page_tab = mmap_find_first_free_block();
|
|
||||||
elf_page_dir[768] = ((uint32_t)boot_page_tab - KERNEL_VMA) | 3;
|
|
||||||
elf_page_dir[PAGE_DIR_INDEX(elf->e_entry)] = ((uint32_t)elf_page_tab - KERNEL_VMA) | 7;
|
|
||||||
for (int i = 0; i < 1024; i++) {
|
|
||||||
elf_page_tab[i] = (elf_phys + 0x1000*i) | 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
asm volatile ("mov %0, %%cr3" :: "r"((uint32_t)elf_page_dir - KERNEL_VMA));
|
LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", task.eip, task.esp);
|
||||||
|
jmp_user_mode(task.esp, task.eip);
|
||||||
uint32_t stack = (uint32_t)mmap_find_first_free_block();
|
|
||||||
LOG("Switching to ring 3... EIP: 0x%08X ESP: 0x%08X\n", elf->e_entry+text->sh_offset, stack+0x1000);
|
|
||||||
jmp_user_mode(stack+0x1000, elf->e_entry+text->sh_offset);
|
|
||||||
|
|
||||||
halt:
|
halt:
|
||||||
for (;;) {}
|
for (;;) {}
|
||||||
|
|
39
kernel/task.c
Normal file
39
kernel/task.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <kernel/task.h>
|
||||||
|
#include <kernel/mem.h>
|
||||||
|
|
||||||
|
extern uint32_t boot_page_tab[1024];
|
||||||
|
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;
|
||||||
|
// Allocate a page for a stack
|
||||||
|
task->esp = (uint32_t)mmap_find_first_free_block() + 0x1000;
|
||||||
|
|
||||||
|
uint32_t *page_dir = mmap_find_first_free_block();
|
||||||
|
task->cr3 = (uint32_t)page_dir - KERNEL_VMA;
|
||||||
|
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;
|
||||||
|
// 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
|
||||||
|
else page_dir[i] = 6;
|
||||||
|
}
|
||||||
|
// Map the ELF image to its specified entry
|
||||||
|
// This will cause problems if the ELF image is larger than 4 MiB so I need to fix this
|
||||||
|
page_dir[PAGE_DIR_INDEX(elf->e_entry)] = ((uint32_t)page_tab - KERNEL_VMA) | 7;
|
||||||
|
uint32_t elf_phys = (uint32_t)elf - KERNEL_VMA;
|
||||||
|
for (int i = 0; i < 1024; i++) {
|
||||||
|
page_tab[i] = (elf_phys + 0x1000*i) | 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void schedule(void) {
|
||||||
|
// If there's only one task running
|
||||||
|
if (!ctx.current_task->next) return;
|
||||||
|
}
|
14
lib/strcmp.h
Normal file
14
lib/strcmp.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef HAZEL_STRCMP_H_
|
||||||
|
#define HAZEL_STRCMP_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int strcmp(const char *str1, const char *str2) {
|
||||||
|
while (*str1 && (*str1 == *str2)) {
|
||||||
|
str1++;
|
||||||
|
str2++;
|
||||||
|
}
|
||||||
|
return *(uint8_t *)str1 - *(uint8_t *)str2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user