KraKern

C++ Kernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/KraKern

commit 280c0ea5ec731bc9fddda9b6f758ea6fb40ba7ad
parent f9dc40f84289df62cdcc7efbb4473ae40d820a98
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Mon, 22 Feb 2016 16:32:29 +0100

Work(Multi-Tasking): Some work on the scheduler, not stable yet

Diffstat:
Mboot/x86/GDT.cpp | 4++++
Mboot/x86/IDT.cpp | 5+++--
Mboot/x86/x86.asm | 39+++++++++++++++++++++++++++++++++++++++
Mincludes/boot/x86.hpp | 3+++
Mincludes/core/Kernel.hpp | 2++
Aincludes/core/Scheduler.hpp | 19+++++++++++++++++++
Mkernel/Io.cpp | 1+
Mkernel/Kernel.cpp | 2++
Mkernel/Makefile | 2+-
Mkernel/ProcessTable.cpp | 2+-
Akernel/Scheduler.cpp | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 171 insertions(+), 4 deletions(-)

diff --git a/boot/x86/GDT.cpp b/boot/x86/GDT.cpp @@ -32,6 +32,7 @@ void GDT::_init_gdt(void) { this->_init_gdt_desc((u32)&t_default, 0x67, 0xE9, 0x00, &this->_gdtdesc[7]); this->_gdtr.limite = GDT_MAX * 8; this->_gdtr.base = GDT_BASE; + this->_default_tss = t_default; memcpy((char *)this->_gdtr.base, (char *)this->_gdtdesc, this->_gdtr.limite); gdtr = this->_gdtr; asm("lgdtl (gdtr)"); @@ -53,3 +54,6 @@ void GDT::_init_gdt_desc(u32 base, u32 limite, u8 acces, u8 other, struct gdtdes desc->other = (other & 0xf); desc->base24_31 = (base & 0xff000000) >> 24; } + +struct tss GDT::get_tss(void) { return this->_default_tss; }; +void GDT::set_tss(struct tss t) { this->_default_tss = t; }; diff --git a/boot/x86/IDT.cpp b/boot/x86/IDT.cpp @@ -17,7 +17,9 @@ extern "C" { } void isr_schedule_int(void) { - //__kern.io.puts("Tick!\n"); + __kern.sch.tick(); + __kern.io.obyte(0x20,0x20); + __kern.io.obyte(0xA0,0x20); } void isr_GP_exc(void) { @@ -38,7 +40,6 @@ void IDT::init(void) { __kern.io.loading("Programmable Interrupts Controller ..."); this->_init_pic(); __kern.io.done(); - asm("sti"); } void IDT::_init_idt(void) { diff --git a/boot/x86/x86.asm b/boot/x86/x86.asm @@ -71,3 +71,42 @@ _asm_schedule: INTERRUPT 1 INTERRUPT 2 + +global do_switch + +do_switch: + mov esi, [esp] + pop eax + + push dword [esi + 4] + push dword [esi + 8] + push dword [esi + 12] + push dword [esi + 16] + push dword [esi + 24] + push dword [esi + 28] + push dword [esi + 32] + push dword [esi + 48] + push dword [esi + 50] + push dword [esi + 52] + push dword [esi + 54] + + mov al, 0x20 + out 0x20, al + + mov eax, [esi + 56] + mov cr3, eax + + pop gs + pop fs + pop es + pop ds + pop edi + pop esi + pop ebp + pop ebx + pop edx + pop ecx + pop eax + + iret + diff --git a/includes/boot/x86.hpp b/includes/boot/x86.hpp @@ -63,12 +63,15 @@ class GDT { public: void init(void); + struct tss get_tss(void); + void set_tss(struct tss t); private: void _init_gdt(void); void _init_gdt_desc(u32 base, u32 limite, u8 acces, u8 other, struct gdtdesc *desc); struct gdtr _gdtr; struct gdtdesc _gdtdesc[GDT_MAX]; + struct tss _default_tss; }; /** diff --git a/includes/core/Kernel.hpp b/includes/core/Kernel.hpp @@ -9,6 +9,7 @@ # include <FileSystem.hpp> # include <ProcessTable.hpp> # include <IDE.hpp> +# include <Scheduler.hpp> class Modules; @@ -28,6 +29,7 @@ class Kernel { ProcessTable pt; Modules *mods; IDE ide; + Scheduler sch; }; # include <Modules.hpp> diff --git a/includes/core/Scheduler.hpp b/includes/core/Scheduler.hpp @@ -0,0 +1,19 @@ +#ifndef __SCHEDULER__ +# define __SCHEDULER__ + +# include <os.h> + +struct process_st; + +class Scheduler { + public: + Scheduler(); + + void tick(void); + private: + void _switch_to_task(process_st *current, int mode); +}; + +# include <Process.hpp> + +#endif diff --git a/kernel/Io.cpp b/kernel/Io.cpp @@ -69,6 +69,7 @@ void Io::putc(char c) { this->_y++; } else if (c == 8 && this->_x) { *(video + 1) = 0x0; + *video = ' '; this->_x--; } else if (c == 9) { this->_x = this->_x + 8 - (this->_x % 8); diff --git a/kernel/Kernel.cpp b/kernel/Kernel.cpp @@ -40,8 +40,10 @@ void Kernel::init(multiboot_info *mbi) { this->fs.init(); this->pt = *(new ProcessTable()); this->pt.init(); + this->sch = *(new Scheduler()); this->ready(); __kern.io.puts("\n"); + asm("sti"); //list_files(this->fs.get_root(), 0); while (1); } diff --git a/kernel/Makefile b/kernel/Makefile @@ -1 +1 @@ -OBJS += kernel/main.o kernel/Io.o kernel/Kernel.o kernel/Memory.o kernel/Process.o kernel/File.o kernel/FileSystem.o kernel/ProcessTable.o kernel/Modules.o kernel/IDE.o +OBJS += kernel/main.o kernel/Io.o kernel/Kernel.o kernel/Memory.o kernel/Process.o kernel/File.o kernel/FileSystem.o kernel/ProcessTable.o kernel/Modules.o kernel/IDE.o kernel/Scheduler.o diff --git a/kernel/ProcessTable.cpp b/kernel/ProcessTable.cpp @@ -21,7 +21,7 @@ void ProcessTable::fork(process_st *info, process_st *father) { info->pd = __kern.mem.pd_copy(father->pd); } -int ProcessTable::create_proc(process_st *info, char *f, int ac, char **av) { +int ProcessTable::create_proc(process_st *info, char *f, int ac, char **av) { struct page *kstack; process_st *previous, *current; char **param, **uparam; diff --git a/kernel/Scheduler.cpp b/kernel/Scheduler.cpp @@ -0,0 +1,96 @@ +# include <Scheduler.hpp> + +Scheduler::Scheduler(void) { + return ; +} + +void Scheduler::tick(void) { + Process *pcurrent = __kern.pt.get_current(), *plist = __kern.pt.get_list(); + process_st *current, *p; + u32 *stack_ptr; + struct tss dtss; + + if (!pcurrent || (!pcurrent->get_p_next() && plist == pcurrent)) + return ; + current = pcurrent->get_p_info(); + dtss = __kern.gdt.get_tss(); + asm("mov (%%ebp), %%eax; mov %%eax, %0": "=m"(stack_ptr):); + current->regs.eflags = stack_ptr[16]; + current->regs.cs = stack_ptr[15]; + current->regs.eip = stack_ptr[14]; + current->regs.eax = stack_ptr[13]; + current->regs.ecx = stack_ptr[12]; + current->regs.edx = stack_ptr[11]; + current->regs.ebx = stack_ptr[10]; + current->regs.ebp = stack_ptr[8]; + current->regs.esi = stack_ptr[7]; + current->regs.edi = stack_ptr[6]; + current->regs.ds = stack_ptr[5]; + current->regs.es = stack_ptr[4]; + current->regs.fs = stack_ptr[3]; + current->regs.gs = stack_ptr[2]; + if (current->regs.cs == 0x08) { + current->regs.esp = stack_ptr[17]; + current->regs.ss = stack_ptr[18]; + } else { + current->regs.esp = stack_ptr[9] + 12; + current->regs.ss = dtss.ss0; + } + + current->kstack.ss0 = dtss.ss0; + current->kstack.esp0 = dtss.esp0; + __kern.io.printk("Schedule %s\n", pcurrent->get_name()); + pcurrent = pcurrent->schedule(); + p = pcurrent->get_p_info(); + if (p->regs.cs != 0x08) { + this->_switch_to_task(p, USERMODE); + } else { + this->_switch_to_task(p, KERNELMODE); + } +} + +void Scheduler::_switch_to_task(process_st *current, int mode) { + u32 kesp, eflags; + u16 kss, ss, cs; + struct tss t = __kern.gdt.get_tss(); + + // signals + t.ss0 = current->kstack.ss0; + t.esp0 = current->kstack.esp0; + __kern.gdt.set_tss(t); + ss = current->regs.ss; + cs = current->regs.cs; + eflags = (current->regs.eflags | 0x200) & 0xFFFFBFFF; + if (mode == USERMODE) { + kss = current->kstack.ss0; + kesp = current->kstack.esp0; + } else { + kss = current->regs.ss; + kesp = current->regs.esp; + } + __kern.io.printk("Switching to %x", current->regs.eip); + asm(" mov %0, %%ss; \ + mov %1, %%esp; \ + cmp %[KMODE], %[mode]; \ + je nextt; \ + push %2; \ + push %3; \ + nextt: \ + push %4; \ + push %5; \ + push %6; \ + push %7; \ + ljmp $0x08, $do_switch" + :: \ + "m"(kss), \ + "m"(kesp), \ + "m"(ss), \ + "m"(current->regs.esp), \ + "m"(eflags), \ + "m"(cs), \ + "m"(current->regs.eip), \ + "m"(current), \ + [KMODE] "i"(KERNELMODE), \ + [mode] "g"(mode) + ); +}