diff options
author | Alexis211 <alexis211@gmail.com> | 2009-10-17 18:20:46 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2009-10-17 18:20:46 +0200 |
commit | ae49f59cc96e4ff3709c857b848132e82e6e0b14 (patch) | |
tree | 46c53db51b25c2deea0786d043e53ab09b647ee0 /Source/Kernel/TaskManager | |
parent | 9520a1a101b264abe700c3f7753f5f55bba4c681 (diff) | |
download | Melon-ae49f59cc96e4ff3709c857b848132e82e6e0b14.tar.gz Melon-ae49f59cc96e4ff3709c857b848132e82e6e0b14.zip |
User mode code can now run !
We have a sample process (hardcoded in ASM in Task.wtf.asm) that
displays a's and sleeps 20ms, but it's on a hidden virtual terminal so
it's useless :D
Diffstat (limited to 'Source/Kernel/TaskManager')
-rw-r--r-- | Source/Kernel/TaskManager/Task.ns.cpp | 5 | ||||
-rw-r--r-- | Source/Kernel/TaskManager/Task.wtf.asm | 15 | ||||
-rw-r--r-- | Source/Kernel/TaskManager/Thread.class.cpp | 59 | ||||
-rw-r--r-- | Source/Kernel/TaskManager/Thread.class.h | 1 |
4 files changed, 73 insertions, 7 deletions
diff --git a/Source/Kernel/TaskManager/Task.ns.cpp b/Source/Kernel/TaskManager/Task.ns.cpp index a34f14f..1d1676e 100644 --- a/Source/Kernel/TaskManager/Task.ns.cpp +++ b/Source/Kernel/TaskManager/Task.ns.cpp @@ -94,8 +94,11 @@ void doSwitch() { eip = t->getEip(); cr3 = currentProcess->getPagedir()->physicalAddr; + asm volatile("cli"); + + t->setKernelStack(); + asm volatile(" \ - cli; \ mov %0, %%ebp; \ mov %1, %%esp; \ mov %2, %%ecx; \ diff --git a/Source/Kernel/TaskManager/Task.wtf.asm b/Source/Kernel/TaskManager/Task.wtf.asm index 77db18e..2e5b9f8 100644 --- a/Source/Kernel/TaskManager/Task.wtf.asm +++ b/Source/Kernel/TaskManager/Task.wtf.asm @@ -47,3 +47,18 @@ copy_page_physical: popf ; Pop EFLAGS back. pop ebx ; Get the original value of EBX back. ret + + +[GLOBAL sample_task] +sample_task: + mov eax, 0x00000001 ;temporarily defined as syscall id for writing one char to screen + mov ebx, 'a' ;loopingly write a's to screen + int 64 + mov eax, 0x00000002 ;temporary syscall for sleeping + mov ebx, 20 ;20ms + int 64 + jmp sample_task + int 66 ;finish task - will never happen since we have an infinite loop +[GLOBAL sample_task_size] +sample_task_size: + dd sample_task_size - sample_task diff --git a/Source/Kernel/TaskManager/Thread.class.cpp b/Source/Kernel/TaskManager/Thread.class.cpp index 6d62474..63d8160 100644 --- a/Source/Kernel/TaskManager/Thread.class.cpp +++ b/Source/Kernel/TaskManager/Thread.class.cpp @@ -2,11 +2,51 @@ #include <TaskManager/Task.ns.h> #include <MemoryManager/PageAlloc.ns.h> #include <DeviceManager/Time.ns.h> +#include <MemoryManager/GDT.ns.h> void runThread(Thread* thread, void* data, thread_entry_t entry_point) { - asm volatile("sti"); - u32int ret = entry_point(data); //Run ! - asm volatile("mov %0, %%eax; int $66;" : : "r"(ret)); //Syscall for thread ending + if (thread->m_isKernel) { + asm volatile("sti"); + u32int ret = entry_point(data); //Run ! + asm volatile("mov %0, %%eax; int $66;" : : "r"(ret)); //Syscall for thread ending + } else { + //Setup values on user stack + u32int *stack = (u32int*)((u32int)thread->m_userStack.addr + thread->m_userStack.size); + stack--; + *stack = (u32int)data; + stack--; + *stack = 0; + u32int esp = (u32int)stack, eip = (u32int)entry_point; + //Setup a false structure for returning from an interrupt : + //- update data segments to 0x23 = user data segment with RPL=3 + //- mov esp in ebx and eip in ecx + //- push value for ss : 0x23 (user data seg rpl3) + //- push value for esp + //- push flags + //- update flags, set IF = 1 (interrupts flag) + //- push value for cs : 0x1B = user code segment with RPL=3 + //- push eip + //- return from fake interrupt + asm volatile(" \ + mov $0x23, %%ax; \ + mov %%ax, %%ds; \ + mov %%ax, %%es; \ + mov %%ax, %%fs; \ + mov %%ax, %%gs; \ + \ + mov %0, %%ebx; \ + mov %1, %%ecx; \ + pushl $0x23; \ + pushl %%ebx; \ + pushf; \ + pop %%eax; \ + or $0x200, %%eax; \ + push %%eax; \ + pushl $0x1B; \ + push %%ecx; \ + iret; \ + " : : "r"(esp), "r"(eip)); + } } Thread::Thread() { //Private constructor, does nothing @@ -27,7 +67,10 @@ Thread::Thread(Process* process, thread_entry_t entry_point, void* data) { Thread::~Thread() { Task::unregisterThread(this); Mem::kfree(m_kernelStack.addr); - if (!m_isKernel) m_process->heap().free(m_userStack.addr); + if (m_userStack.addr != 0) { + m_process->getPagedir()->switchTo(); + m_process->heap().free(m_userStack.addr); + } //Don't unregister thread in process, it has probably already been done } @@ -111,11 +154,11 @@ void Thread::handleException(registers_t regs, int no) { *(m_process->m_vt) << "At:" << (u32int)faddr; *(m_process->m_vt) << "\nThread finishing.\n"; - finish(E_PAGEFAULT); + Task::currentThreadExits(E_PAGEFAULT); //Calling this will setup a new stack return; } *(m_process->m_vt) << "\nThread finishing.\n"; - finish(E_UNHANDLED_EXCEPTION); + Task::currentThreadExits(E_UNHANDLED_EXCEPTION); } void Thread::setState(u32int esp, u32int ebp, u32int eip) { @@ -124,6 +167,10 @@ void Thread::setState(u32int esp, u32int ebp, u32int eip) { m_eip = eip; } +void Thread::setKernelStack() { + GDT::tss_entry.esp0 = (u32int)(m_kernelStack.addr) + m_kernelStack.size; +} + u32int Thread::getEsp() { return m_esp; } u32int Thread::getEbp() { return m_ebp; } u32int Thread::getEip() { return m_eip; } diff --git a/Source/Kernel/TaskManager/Thread.class.h b/Source/Kernel/TaskManager/Thread.class.h index 9c8fa26..aeb1f93 100644 --- a/Source/Kernel/TaskManager/Thread.class.h +++ b/Source/Kernel/TaskManager/Thread.class.h @@ -43,6 +43,7 @@ class Thread { void handleException(registers_t regs, int no); void setState(u32int esp, u32int ebp, u32int eip); + void setKernelStack(); u32int getEsp(); u32int getEbp(); u32int getEip(); |