Commit 9cced14598a09efa2f3708386950b05a0712b8bc
- Diff rendering mode:
- inline
- side by side
kernel/arch/x86/idt.cc
(5 / 3)
|   | |||
| 177 | 177 | cout.set_colour(7, 0); | |
| 178 | 178 | cout << "\n\nIllegal Exception - " << (const char *)idt::exceptionMessages[r.int_no]; | |
| 179 | 179 | ||
| 180 | cout << endl << endl << "Instruction pointer: "; | ||
| 181 | textmode::puthex(r.eip); | ||
| 182 | |||
| 180 | 183 | cout << "\n\nPlease restart your computer."; | |
| 181 | 184 | ||
| 182 | 185 | // We'll just halt for now, but once we have multitasking, | |
| … | … | ||
| 199 | 199 | // Handle IRQs - called from the assembly stubs | |
| 200 | 200 | void irq_handler(registers_t r) | |
| 201 | 201 | { | |
| 202 | |||
| 203 | 202 | if (r.int_no >= 40) | |
| 204 | 203 | { | |
| 205 | 204 | // Send reset signal to slave PIC | |
| … | … | ||
| 212 | 212 | if(idt::interrupt_handlers[r.int_no] != 0) | |
| 213 | 213 | { | |
| 214 | 214 | // Run the handler | |
| 215 | idt::isr_t irq_handler = idt::interrupt_handlers[r.int_no]; | ||
| 215 | idt::isr_t handler = idt::interrupt_handlers[r.int_no]; | ||
| 216 | 216 | ||
| 217 | irq_handler(r); | ||
| 217 | handler(r); | ||
| 218 | 218 | } | |
| 219 | 219 | } |
kernel/arch/x86/idt.h
(1 / 1)
|   | |||
| 8 | 8 | { | |
| 9 | 9 | bool initialise(); | |
| 10 | 10 | ||
| 11 | typedef void (*isr_t)(registers_t); | ||
| 11 | typedef void (*isr_t)(registers_t &); | ||
| 12 | 12 | ||
| 13 | 13 | void register_irq(u32int irq, isr_t handler); | |
| 14 | 14 | void register_isr(u32int irq, isr_t handler); |
kernel/arch/x86/keyboard.cc
(1 / 1)
|   | |||
| 129 | 129 | idt::register_irq(1, &keyboard::callback); | |
| 130 | 130 | } | |
| 131 | 131 | ||
| 132 | void callback(registers_t) | ||
| 132 | void callback(registers_t &) | ||
| 133 | 133 | { | |
| 134 | 134 | u32int scancode = inb(0x60); | |
| 135 | 135 |
kernel/arch/x86/keyboard.h
(1 / 1)
|   | |||
| 24 | 24 | { | |
| 25 | 25 | void initialise(); | |
| 26 | 26 | ||
| 27 | void callback(registers_t); | ||
| 27 | void callback(registers_t &); | ||
| 28 | 28 | } | |
| 29 | 29 | ||
| 30 | 30 | #endif |
kernel/arch/x86/paging.cc
(28 / 13)
|   | |||
| 100 | 100 | idt::register_isr(14, page_fault); | |
| 101 | 101 | ||
| 102 | 102 | // Enable paging! | |
| 103 | switch_directory(kernel_directory); | ||
| 103 | switch_directory(kernel_directory, true); | ||
| 104 | 104 | ||
| 105 | 105 | // Now we need to initialise a heap for the kernel to use | |
| 106 | 106 | kheap = heap::create_heap(KHeapStart, KHeapStart + KHeapInitialSize, 0xCFFFF000, false, false); | |
| … | … | ||
| 208 | 208 | } | |
| 209 | 209 | } | |
| 210 | 210 | ||
| 211 | void switch_directory(page_directory_t * dir) | ||
| 211 | void switch_directory(page_directory_t * dir, bool enable) | ||
| 212 | 212 | { | |
| 213 | 213 | // Set the current directory to dir | |
| 214 | 214 | current_directory = dir; | |
| … | … | ||
| 216 | 216 | // Set CR3 to the physical address of the page tables | |
| 217 | 217 | asm volatile("mov %0, %%cr3":: "r"(dir->physicalAddress)); | |
| 218 | 218 | ||
| 219 | // Get the contents of the CR0 register | ||
| 220 | u32int cr0; | ||
| 221 | asm volatile("mov %%cr0, %0": "=r"(cr0)); | ||
| 219 | // Check we need to enable paging | ||
| 220 | if(enable) | ||
| 221 | { | ||
| 222 | // Get the contents of the CR0 register | ||
| 223 | u32int cr0; | ||
| 224 | asm volatile("mov %%cr0, %0": "=r"(cr0)); | ||
| 222 | 225 | ||
| 223 | // Set the bit in the CR0 register to enable paging | ||
| 224 | cr0 |= 0x80000000; | ||
| 226 | // Set the bit in the CR0 register to enable paging | ||
| 227 | cr0 |= 0x80000000; | ||
| 225 | 228 | ||
| 226 | // Enable paging! | ||
| 227 | asm volatile("mov %0, %%cr0":: "r"(cr0)); | ||
| 229 | // Enable paging! | ||
| 230 | asm volatile("mov %0, %%cr0":: "r"(cr0)); | ||
| 231 | } | ||
| 228 | 232 | } | |
| 229 | 233 | ||
| 230 | 234 | page_t * get_page(uintptr address, bool make, page_directory_t * dir) | |
| … | … | ||
| 340 | 340 | } | |
| 341 | 341 | ||
| 342 | 342 | // The function to handle a page fault. | |
| 343 | void page_fault(registers_t regs) | ||
| 343 | void page_fault(registers_t ®s) | ||
| 344 | 344 | { | |
| 345 | // Disable interrupts | ||
| 346 | disable(); | ||
| 347 | |||
| 348 | cout.set_colour(4, 0); | ||
| 349 | cout << "\n\nSymmetry encountered a fatal error:"; | ||
| 350 | |||
| 351 | cout.set_colour(7, 0); | ||
| 352 | |||
| 345 | 353 | // The fault address is stored in the CR2 register | |
| 346 | 354 | uintptr faulting_address; | |
| 347 | 355 | asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); | |
| … | … | ||
| 359 | 359 | int rw = regs.err_code & 0x2; // Write operation | |
| 360 | 360 | int user = regs.err_code & 0x4; // Was in user mode? | |
| 361 | 361 | int reserved = regs.err_code & 0x8; // Overwritten CPU-reserved bits of entry? | |
| 362 | //int id = regs.err_code & 0x10; // Caused by instruction fetch? | ||
| 363 | 362 | ||
| 364 | cout << "\n\nPage Fault -"; | ||
| 363 | cout << endl << endl << "Page Fault -"; | ||
| 365 | 364 | ||
| 366 | 365 | if(present) { cout << " page not present -"; } | |
| 367 | 366 | if(rw) { cout << " read only -"; } | |
| … | … | ||
| 370 | 370 | cout << " at "; | |
| 371 | 371 | textmode::puthex(faulting_address); | |
| 372 | 372 | ||
| 373 | panic("Page Fault"); | ||
| 373 | cout << endl << endl << "EIP: "; | ||
| 374 | textmode::puthex(regs.eip); | ||
| 375 | |||
| 376 | // Halt indefinetely | ||
| 377 | halt(); | ||
| 374 | 378 | } | |
| 375 | 379 | } |
kernel/arch/x86/paging.h
(2 / 2)
|   | |||
| 39 | 39 | void initialise(); | |
| 40 | 40 | ||
| 41 | 41 | // Switch to a different page directory | |
| 42 | void switch_directory(page_directory_t * dir); | ||
| 42 | void switch_directory(page_directory_t * dir, bool enable = false); | ||
| 43 | 43 | ||
| 44 | 44 | // Return a page which is mapped to a particular address | |
| 45 | 45 | page_t * get_page(uintptr address, bool make, page_directory_t * dir); | |
| … | … | ||
| 49 | 49 | void allocate_frame(page_t * page, bool kernel, bool writable); | |
| 50 | 50 | ||
| 51 | 51 | // The exception handler function for page faults | |
| 52 | void page_fault(registers_t regs); | ||
| 52 | void page_fault(registers_t ®s); | ||
| 53 | 53 | ||
| 54 | 54 | // Clone a page directory | |
| 55 | 55 | page_directory_t * clone_directory(page_directory_t * src); |
kernel/arch/x86/stack.cc
(95 / 0)
|   | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2009 Stephen Gentle | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "common.h" | ||
| 18 | #include "stack.h" | ||
| 19 | #include "paging.h" | ||
| 20 | #include "memory.h" | ||
| 21 | |||
| 22 | extern paging::page_directory_t * current_directory; | ||
| 23 | |||
| 24 | namespace stack | ||
| 25 | { | ||
| 26 | // Move the current stack to [new_stack_start] | ||
| 27 | void move_stack(void * new_stack_start, size_t size, uintptr initial_esp) | ||
| 28 | { | ||
| 29 | // Retrieve the old stack and base pointers | ||
| 30 | uintptr old_stack_pointer; | ||
| 31 | uintptr old_base_pointer; | ||
| 32 | |||
| 33 | asm volatile("mov %%esp, %0" : "=r" (old_stack_pointer)); | ||
| 34 | asm volatile("mov %%ebp, %0" : "=r" (old_base_pointer)); | ||
| 35 | |||
| 36 | // Calculate offset and stack and base pointers to our new stack | ||
| 37 | uintptr offset = (uintptr)new_stack_start - initial_esp; | ||
| 38 | uintptr new_stack_pointer = old_stack_pointer + offset; | ||
| 39 | uintptr new_base_pointer = old_base_pointer + offset; | ||
| 40 | |||
| 41 | // Copy the stack | ||
| 42 | copy_stack(new_stack_start, size, initial_esp); | ||
| 43 | |||
| 44 | // Switch to the new stack | ||
| 45 | asm volatile("mov %0, %%esp" : : "r" (new_stack_pointer)); | ||
| 46 | asm volatile("mov %0, %%ebp" : : "r" (new_base_pointer)); | ||
| 47 | } | ||
| 48 | |||
| 49 | // Move the current stack to [new_stack_start] | ||
| 50 | void copy_stack(void * new_stack_start, size_t size, uintptr initial_esp) | ||
| 51 | { | ||
| 52 | // Allocate space for the new stack | ||
| 53 | for(uintptr i = (uintptr)new_stack_start; i >= ((uintptr)new_stack_start - size); i -= PageSize) | ||
| 54 | { | ||
| 55 | // The stack should be user mode and writable | ||
| 56 | paging::allocate_frame(paging::get_page(i, true, current_directory), false, true); | ||
| 57 | } | ||
| 58 | |||
| 59 | // Flush the TLB by reading and writing the directory address | ||
| 60 | uintptr pd_addr; | ||
| 61 | asm volatile("mov %%cr3, %0" : "=r" (pd_addr)); | ||
| 62 | asm volatile("mov %0, %%cr3" : : "r" (pd_addr)); | ||
| 63 | |||
| 64 | uintptr old_stack_pointer; | ||
| 65 | uintptr old_base_pointer; | ||
| 66 | |||
| 67 | // Retrieve the old stack and base pointers | ||
| 68 | asm volatile("mov %%esp, %0" : "=r" (old_stack_pointer)); | ||
| 69 | asm volatile("mov %%ebp, %0" : "=r" (old_base_pointer)); | ||
| 70 | |||
| 71 | // Calculate offset and stack and base pointers to our new stack | ||
| 72 | uintptr offset = (uintptr)new_stack_start - initial_esp; | ||
| 73 | uintptr new_stack_pointer = old_stack_pointer + offset; | ||
| 74 | //uintptr new_base_pointer = old_base_pointer + offset; | ||
| 75 | |||
| 76 | // Copy the old stack to our net stack location | ||
| 77 | memcpy((void *)new_stack_pointer, (void *)old_stack_pointer, initial_esp - old_stack_pointer); | ||
| 78 | |||
| 79 | // Recurse through all the values in the new stack | ||
| 80 | for(uintptr i = (uintptr)new_stack_start; i < (uintptr)new_stack_start - size; i -= 4) | ||
| 81 | { | ||
| 82 | uintptr temp = *(uintptr *)i; | ||
| 83 | |||
| 84 | // Assume that temp is a base pointer if it is in the range of the old stack, and | ||
| 85 | // translate it to our new stack location. | ||
| 86 | // This will also remap any other pointers that coincidentally fall in this range. | ||
| 87 | if((old_stack_pointer < temp) && (temp < initial_esp)) | ||
| 88 | { | ||
| 89 | temp = temp + offset; | ||
| 90 | uintptr * temp2 = (uintptr *)i; | ||
| 91 | *temp2 = temp; | ||
| 92 | } | ||
| 93 | }; | ||
| 94 | } | ||
| 95 | } |
kernel/arch/x86/stack.h
(31 / 0)
|   | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2009 Stephen Gentle | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef STACK_H | ||
| 18 | #define STACK_H | ||
| 19 | |||
| 20 | #include "common.h" | ||
| 21 | |||
| 22 | namespace stack | ||
| 23 | { | ||
| 24 | // Copy the current stack and switch to it | ||
| 25 | void move_stack(void * new_stack_start, size_t size, uintptr initial_esp); | ||
| 26 | |||
| 27 | // Copy the current stack | ||
| 28 | void copy_stack(void * new_stack_start, size_t size, uintptr initial_esp); | ||
| 29 | } | ||
| 30 | |||
| 31 | #endif |
kernel/arch/x86/task.cc
(0 / 62)
|   | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008 Stephen Gentle | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | // Platform dependant multatasking code | ||
| 18 | |||
| 19 | #include "common.h" | ||
| 20 | #include "paging.h" | ||
| 21 | |||
| 22 | #include "mm/virtual_address_space.h" | ||
| 23 | |||
| 24 | namespace multitasking | ||
| 25 | { | ||
| 26 | // Read the value of the register esp | ||
| 27 | uintptr read_esp() | ||
| 28 | { | ||
| 29 | uintptr temp; | ||
| 30 | |||
| 31 | asm volatile("mov %%esp, %0" : "=r"(temp)); | ||
| 32 | |||
| 33 | return temp; | ||
| 34 | } | ||
| 35 | |||
| 36 | // Read the value of the register ebp | ||
| 37 | uintptr read_ebp() | ||
| 38 | { | ||
| 39 | uintptr temp; | ||
| 40 | |||
| 41 | asm volatile("mov %%ebp, %0" : "=r"(temp)); | ||
| 42 | |||
| 43 | return temp; | ||
| 44 | } | ||
| 45 | |||
| 46 | void switch_tasks(uintptr eip, uintptr esp, uintptr ebp, virtual_address_space * addr) | ||
| 47 | { | ||
| 48 | // Get the page directory from the virtual address space | ||
| 49 | uintptr page_dir_address = addr->get_page_directory()->physicalAddress; | ||
| 50 | |||
| 51 | asm volatile(" \ | ||
| 52 | cli; \ | ||
| 53 | mov %0, %%ecx; \ | ||
| 54 | mov %1, %%esp; \ | ||
| 55 | mov %2, %%ebp; \ | ||
| 56 | mov %3, %%cr3; \ | ||
| 57 | mov $0x12345, %%eax; \ | ||
| 58 | sti; \ | ||
| 59 | jmp *%%ecx" | ||
| 60 | : : "r"(eip), "r"(esp), "r"(ebp), "r"(page_dir_address)); | ||
| 61 | } | ||
| 62 | } |
kernel/arch/x86/timer.cc
(3 / 3)
|   | |||
| 27 | 27 | size_t ticks = 0; | |
| 28 | 28 | ||
| 29 | 29 | // The callback that the timer interrupt will execute | |
| 30 | void callback(registers_t); | ||
| 30 | void callback(registers_t &r); | ||
| 31 | 31 | ||
| 32 | 32 | void initialise(u32int frequency) | |
| 33 | 33 | { | |
| … | … | ||
| 62 | 62 | outb(0x40, higher); | |
| 63 | 63 | } | |
| 64 | 64 | ||
| 65 | void callback(registers_t) | ||
| 65 | void callback(registers_t &r) | ||
| 66 | 66 | { | |
| 67 | 67 | // Increment the tick counter | |
| 68 | 68 | ticks++; | |
| 69 | 69 | ||
| 70 | 70 | // It's time to run another process | |
| 71 | scheduler::schedule(); | ||
| 71 | scheduler::schedule(r); | ||
| 72 | 72 | } | |
| 73 | 73 | ||
| 74 | 74 | size_t get_ticks() |
kernel/kernel.cc
(33 / 4)
|   | |||
| 32 | 32 | ||
| 33 | 33 | using namespace std; | |
| 34 | 34 | ||
| 35 | namespace textmode | ||
| 36 | { | ||
| 37 | extern u32int position; | ||
| 38 | |||
| 39 | void setpos(u32int p); | ||
| 40 | |||
| 41 | void setpos(u32int p) { position = p; } | ||
| 42 | } | ||
| 43 | |||
| 35 | 44 | // Show messages on startup? | |
| 36 | 45 | bool quiet_boot = false; | |
| 37 | 46 | ||
| … | … | ||
| 70 | 70 | cout.set_colour(7, 0); | |
| 71 | 71 | ||
| 72 | 72 | // Test elf executable parsing | |
| 73 | elf32::test("hello"); | ||
| 73 | //elf32::test("hello"); | ||
| 74 | 74 | ||
| 75 | 75 | cout.set_colour(2, 0); | |
| 76 | 76 | cout << "\n\nYou can test the keyboard driver by typing here. Press ESC to shut down." << endl; | |
| 77 | 77 | cout.set_colour(7, 0); | |
| 78 | 78 | ||
| 79 | // Just loop while we wait for interrupts | ||
| 79 | // The kernel has finished initialising. All kernel code run from this point will be the result | ||
| 80 | // of interrupts or system calls. | ||
| 80 | 81 | for(; ;) | |
| 81 | 82 | { | |
| 82 | |||
| 83 | // This is a test for threading | ||
| 84 | /* textmode::setpos(0); | ||
| 85 | cout << "KERNEL!"; | ||
| 86 | scheduler::sleep(1000); | ||
| 87 | textmode::setpos(0); | ||
| 88 | cout << " "; | ||
| 89 | scheduler::sleep(1000);*/ | ||
| 83 | 90 | } | |
| 84 | 91 | ||
| 85 | 92 | // If we break the loop for some reason, just shutdown | |
| 86 | 93 | kernel::shutdown(); | |
| 87 | 94 | } | |
| 88 | 95 | ||
| 96 | int test_thread(void *) | ||
| 97 | { | ||
| 98 | for(; ;) | ||
| 99 | { | ||
| 100 | textmode::setpos(20); | ||
| 101 | cout << "THREAD!"; | ||
| 102 | scheduler::sleep(500); | ||
| 103 | textmode::setpos(20); | ||
| 104 | cout << " "; | ||
| 105 | scheduler::sleep(500); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 89 | 109 | namespace kernel | |
| 90 | 110 | { | |
| 91 | 111 | void initialise(struct multiboot * ptr) | |
| … | … | ||
| 124 | 124 | } | |
| 125 | 125 | ||
| 126 | 126 | // Scan the initial ramdisk and get it's address | |
| 127 | u32int initrd_address = initrd::scan(ptr); | ||
| 127 | uintptr initrd_address = initrd::scan(ptr); | ||
| 128 | 128 | ||
| 129 | 129 | // Set up virtual memory management | |
| 130 | 130 | paging::initialise(); |
kernel/lib/cstring.cc
(1 / 2)
|   | |||
| 129 | 129 | } | |
| 130 | 130 | ||
| 131 | 131 | ||
| 132 | // Atoi - Cponvert a number in a string into an | ||
| 133 | // integer | ||
| 132 | // Atoi - Convert a number in a string into an integer | ||
| 134 | 133 | u32int atoi(const char * ch, u32int base) | |
| 135 | 134 | { | |
| 136 | 135 | u32int num = 0; |
|   | |||
| 29 | 29 | virtual_address_space::~virtual_address_space() | |
| 30 | 30 | { | |
| 31 | 31 | } | |
| 32 | |||
| 33 | void virtual_address_space::switch_to() | ||
| 34 | { | ||
| 35 | paging::switch_directory(m_page_directory); | ||
| 36 | } |
|   | |||
| 45 | 45 | return m_page_directory; | |
| 46 | 46 | } | |
| 47 | 47 | ||
| 48 | // Switch to this thread's page directory | ||
| 49 | void switch_to(); | ||
| 50 | |||
| 48 | 51 | private: | |
| 49 | 52 | // This address space's page directory | |
| 50 | 53 | paging::page_directory_t * m_page_directory; |
kernel/process/scheduler.cc
(28 / 20)
|   | |||
| 21 | 21 | // The current thread. | |
| 22 | 22 | thread * current_thread = NULL; | |
| 23 | 23 | ||
| 24 | thread * kernel = NULL; | ||
| 25 | thread * other = NULL; | ||
| 26 | #include "iostream.h" | ||
| 27 | |||
| 24 | 28 | namespace scheduler | |
| 25 | 29 | { | |
| 26 | 30 | // Vectors for storing the threads and processes the scheduler will use | |
| … | … | ||
| 34 | 34 | // Keep track of process IDs | |
| 35 | 35 | size_t process_id = 0; | |
| 36 | 36 | ||
| 37 | void schedule() | ||
| 38 | { | ||
| 37 | void schedule(registers_t ®s) | ||
| 38 | { | ||
| 39 | 39 | // If we haven't set up multitasking yet, just exit early | |
| 40 | 40 | if(current_thread == NULL) | |
| 41 | 41 | { | |
| … | … | ||
| 43 | 43 | } | |
| 44 | 44 | ||
| 45 | 45 | // Read the esp, ebp registers | |
| 46 | uintptr esp, ebp, eip; | ||
| 46 | uintptr esp, ebp; | ||
| 47 | |||
| 48 | esp = regs.esp; | ||
| 49 | ebp = regs.ebp; | ||
| 47 | 50 | ||
| 48 | esp = multitasking::read_esp(); | ||
| 49 | ebp = multitasking::read_ebp(); | ||
| 50 | |||
| 51 | // Get the current instruction pointer. | ||
| 52 | eip = read_eip(); | ||
| 53 | |||
| 54 | // If we just executed read_eip, then eip will contain the correct value. We may | ||
| 55 | // have just switched tasks though, and jumped to this address, and in that case | ||
| 56 | // we would have just executed switch_task. We'll set the value to 0x12345 later | ||
| 57 | // on so we know what is happenning now | ||
| 58 | if(eip == 0x12345) | ||
| 59 | { | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | |||
| 63 | 51 | // Save the registers | |
| 64 | current_thread->set_eip(eip); | ||
| 52 | current_thread->set_eip(regs.eip); | ||
| 65 | 53 | current_thread->set_stack_ptr(esp, ebp); | |
| 66 | 54 | ||
| 67 | 55 | // TODO: Get next task in vector | |
| 56 | if(current_thread == kernel) | ||
| 57 | { | ||
| 58 | current_thread = other; | ||
| 59 | other->set_stack_ptr(esp, ebp); | ||
| 60 | } | ||
| 61 | else | ||
| 62 | { | ||
| 63 | current_thread = kernel; | ||
| 64 | } | ||
| 68 | 65 | ||
| 66 | // END TEMP | ||
| 67 | |||
| 69 | 68 | // Switch tasks | |
| 70 | multitasking::switch_tasks(eip, esp, ebp, current_thread->get_parent()->get_address_space()); | ||
| 69 | //multitasking::switch_tasks(eip, esp, ebp, current_thread->get_parent()->get_address_space()); | ||
| 70 | regs.eip = current_thread->get_eip(); | ||
| 71 | regs.esp = current_thread->get_esp(); | ||
| 72 | regs.ebp = current_thread->get_ebp(); | ||
| 73 | |||
| 74 | current_thread->get_parent()->get_address_space()->switch_to(); | ||
| 71 | 75 | } | |
| 72 | 76 | ||
| 73 | 77 | size_t add_process(process * p) |
kernel/process/scheduler.h
(2 / 1)
|   | |||
| 20 | 20 | #include "common.h" | |
| 21 | 21 | #include "process/process.h" | |
| 22 | 22 | #include "process/thread.h" | |
| 23 | #include "isr.h" | ||
| 23 | 24 | ||
| 24 | 25 | namespace scheduler | |
| 25 | 26 | { | |
| 26 | void schedule(); | ||
| 27 | void schedule(registers_t ®s); | ||
| 27 | 28 | ||
| 28 | 29 | // Add a process to the scheduler and return its pid | |
| 29 | 30 | size_t add_process(process * p); |
kernel/process/task.cc
(10 / 54)
|   | |||
| 19 | 19 | #include "scheduler.h" | |
| 20 | 20 | #include "task.h" | |
| 21 | 21 | #include "paging.h" | |
| 22 | #include "stack.h" | ||
| 22 | 23 | ||
| 23 | 24 | extern uintptr initial_esp; | |
| 24 | 25 | extern paging::page_directory_t * current_directory; | |
| 25 | 26 | extern heap::heap * kheap; | |
| 26 | 27 | extern thread * current_thread; | |
| 27 | 28 | ||
| 29 | // TEST | ||
| 30 | extern thread * kernel; | ||
| 31 | extern thread * other; | ||
| 32 | extern int test_thread(void *); | ||
| 33 | // END TEST | ||
| 34 | |||
| 28 | 35 | namespace multitasking | |
| 29 | 36 | { | |
| 30 | 37 | void move_stack(void * new_stack_start, size_t size); | |
| … | … | ||
| 44 | 44 | disable(); | |
| 45 | 45 | ||
| 46 | 46 | // Relocate the stack to a known location | |
| 47 | move_stack((void *)0xE0000000, 0x2000); | ||
| 47 | stack::move_stack((void *)0xE0000000, 0x2000, initial_esp); | ||
| 48 | 48 | ||
| 49 | 49 | // Make a new process for the kernel | |
| 50 | 50 | process * kernel_process = new process(); | |
| … | … | ||
| 53 | 53 | virtual_address_space * addr = new virtual_address_space(current_directory, kheap); | |
| 54 | 54 | kernel_process->set_address_space(addr); | |
| 55 | 55 | ||
| 56 | current_thread = new thread(kernel_process); | ||
| 56 | current_thread = kernel = new thread(kernel_process); | ||
| 57 | other = new thread(kernel_process, test_thread, NULL); | ||
| 57 | 58 | ||
| 58 | 59 | // Re-enable interrupts, starting the scheduler | |
| 59 | 60 | enable(); | |
| 60 | 61 | ||
| 61 | 62 | debug::startup_status(true); | |
| 62 | 63 | } | |
| 63 | |||
| 64 | // Move the initial kernel stack that Grub leaves us with to [new_stack_start] | ||
| 65 | void move_stack(void * new_stack_start, size_t size) | ||
| 66 | { | ||
| 67 | // Allocate space for the new stack | ||
| 68 | for(uintptr i = (uintptr)new_stack_start; i >= ((uintptr)new_stack_start - size); i -= PageSize) | ||
| 69 | { | ||
| 70 | // The stack should be user mode and writable | ||
| 71 | paging::allocate_frame(paging::get_page(i, true, current_directory), false, true); | ||
| 72 | } | ||
| 73 | |||
| 74 | // Flush the TLB by reading and writing the directory address | ||
| 75 | uintptr pd_addr; | ||
| 76 | asm volatile("mov %%cr3, %0" : "=r" (pd_addr)); | ||
| 77 | asm volatile("mov %0, %%cr3" : : "r" (pd_addr)); | ||
| 78 | |||
| 79 | uintptr old_stack_pointer; | ||
| 80 | uintptr old_base_pointer; | ||
| 81 | |||
| 82 | // Retrieve the old stack and base pointers | ||
| 83 | asm volatile("mov %%esp, %0" : "=r" (old_stack_pointer)); | ||
| 84 | asm volatile("mov %%ebp, %0" : "=r" (old_base_pointer)); | ||
| 85 | |||
| 86 | // Calculate offset and stack and base pointers to our new stack | ||
| 87 | uintptr offset = (uintptr)new_stack_start - initial_esp; | ||
| 88 | uintptr new_stack_pointer = old_stack_pointer + offset; | ||
| 89 | uintptr new_base_pointer = old_base_pointer + offset; | ||
| 90 | |||
| 91 | // Copy the old stack to our net stack location | ||
| 92 | memcpy((void *)new_stack_pointer, (void *)old_stack_pointer, initial_esp - old_stack_pointer); | ||
| 93 | |||
| 94 | // Recurse through all the values in the new stack | ||
| 95 | for(uintptr i = (uintptr)new_stack_start; i < (uintptr)new_stack_start - size; i -= 4) | ||
| 96 | { | ||
| 97 | uintptr temp = *(uintptr *)i; | ||
| 98 | |||
| 99 | // Assume that temp is a base pointer if it is in the range of the old stack, and | ||
| 100 | // translate it to our new stack location. | ||
| 101 | // This will also remap any other pointers that coincidentally fall in this range. | ||
| 102 | if((old_stack_pointer < temp) && (temp < initial_esp)) | ||
| 103 | { | ||
| 104 | temp = temp + offset; | ||
| 105 | uintptr * temp2 = (uintptr *)i; | ||
| 106 | *temp2 = temp; | ||
| 107 | } | ||
| 108 | }; | ||
| 109 | |||
| 110 | // Switch to the new stack | ||
| 111 | asm volatile("mov %0, %%esp" : : "r" (new_stack_pointer)); | ||
| 112 | asm volatile("mov %0, %%ebp" : : "r" (new_base_pointer)); | ||
| 113 | } | ||
| 114 | |||
| 115 | 64 | } |
kernel/process/task.h
(0 / 6)
|   | |||
| 25 | 25 | namespace multitasking | |
| 26 | 26 | { | |
| 27 | 27 | void initialise(); | |
| 28 | |||
| 29 | // Defined in platform specific task.cc | ||
| 30 | uintptr read_esp(); | ||
| 31 | uintptr read_ebp(); | ||
| 32 | |||
| 33 | void switch_tasks(uintptr eip, uintptr esp, uintptr ebp, virtual_address_space * addr); | ||
| 34 | 28 | } | |
| 35 | 29 | ||
| 36 | 30 | #endif |
kernel/process/thread.cc
(11 / 0)
|   | |||
| 17 | 17 | #include "process/process.h" | |
| 18 | 18 | #include "process/thread.h" | |
| 19 | 19 | ||
| 20 | #include "iostream.h" | ||
| 21 | |||
| 20 | 22 | thread::thread(process * parent) | |
| 21 | 23 | : m_parent(parent), m_eip(0), m_esp(0), m_ebp(0) | |
| 22 | 24 | { | |
| 23 | 25 | parent->add_thread(this); | |
| 26 | } | ||
| 27 | |||
| 28 | thread::thread(process * parent, ThreadStart start_function, void *) | ||
| 29 | : m_parent(parent), m_eip(0), m_esp(0), m_ebp(0) | ||
| 30 | { | ||
| 31 | parent->add_thread(this); | ||
| 32 | |||
| 33 | m_eip = (uintptr)start_function; | ||
| 34 | //textmode::puthex(m_eip); | ||
| 24 | 35 | } | |
| 25 | 36 | ||
| 26 | 37 | thread::~thread() |
kernel/process/thread.h
(7 / 0)
|   | |||
| 56 | 56 | ||
| 57 | 57 | void set_stack_ptr(uintptr esp, uintptr ebp) { m_esp = esp; m_ebp = ebp; }; | |
| 58 | 58 | ||
| 59 | // Get this thread's registers | ||
| 60 | uintptr get_eip() { return m_eip; }; | ||
| 61 | uintptr get_ebp() { return m_ebp; }; | ||
| 62 | uintptr get_esp() { return m_esp; }; | ||
| 63 | |||
| 64 | |||
| 65 | |||
| 59 | 66 | private: | |
| 60 | 67 | // This thread's parent process | |
| 61 | 68 | process * m_parent; |

