diff --git a/Makefile b/Makefile index 31a4692c..b716801b 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,12 @@ programs/hello/a.out: force_look programs/long/a.out: force_look cd programs/long; ${MAKE} a.out +programs/longone/a.out: force_look + cd programs/longone; ${MAKE} a.out + +programs/longtwo/a.out: force_look + cd programs/longtwo; ${MAKE} a.out + programs/loop/a.out: force_look cd programs/loop; ${MAKE} a.out @@ -27,7 +33,7 @@ hdd.img: dd if=/dev/zero of=hdd.img bs=516096c count=1000 (echo n; echo p; echo 1; echo ""; echo ""; echo t; echo c; echo a; echo 1; echo w;) | sudo fdisk -u -C1000 -S63 -H16 hdd.img -thor.flp: hdd.img bootloader/stage1.bin bootloader/stage2.bin kernel/kernel.bin programs/one/a.out programs/hello/a.out programs/long/a.out programs/loop/a.out +thor.flp: hdd.img bootloader/stage1.bin bootloader/stage2.bin kernel/kernel.bin programs/one/a.out programs/hello/a.out programs/long/a.out programs/loop/a.out programs/longone/a.out programs/longtwo/a.out mkdir -p mnt/fake/ dd if=bootloader/stage1.bin of=hdd.img conv=notrunc dd if=bootloader/stage2.bin of=hdd.img seek=1 conv=notrunc @@ -38,6 +44,8 @@ thor.flp: hdd.img bootloader/stage1.bin bootloader/stage2.bin kernel/kernel.bin sudo /bin/cp programs/one/a.out mnt/fake/one sudo /bin/cp programs/hello/a.out mnt/fake/hello sudo /bin/cp programs/long/a.out mnt/fake/long + sudo /bin/cp programs/longone/a.out mnt/fake/longone + sudo /bin/cp programs/longtwo/a.out mnt/fake/longtwo sudo /bin/cp programs/loop/a.out mnt/fake/loop sleep 0.1 sudo /bin/umount mnt/fake/ diff --git a/cpp.mk b/cpp.mk index fa3382d0..9fe09c5b 100644 --- a/cpp.mk +++ b/cpp.mk @@ -12,6 +12,6 @@ CPP_FLAGS_32=$(COMMON_CPP_FLAGS) $(CPP_FLAGS_LOW) -mpreferred-stack-boundary=4 CPP_FLAGS_64=$(COMMON_CPP_FLAGS) -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 COMMON_LINK_FLAGS=-lgcc -PROGRAM_LINK_FLAGS=-z max-page-size=0x1000 $(COMMON_LINK_FLAGS) -T ../linker.ld +PROGRAM_LINK_FLAGS=$(COMMON_LINK_FLAGS) -z max-page-size=0x1000 -T ../linker.ld PROGRAM_FLAGS=-I../../userlib/include/ diff --git a/kernel/include/process.hpp b/kernel/include/process.hpp index df60de01..945e8af0 100644 --- a/kernel/include/process.hpp +++ b/kernel/include/process.hpp @@ -12,6 +12,7 @@ #include "stl/vector.hpp" #include "paging.hpp" +#include "interrupts.hpp" namespace scheduler { @@ -25,19 +26,16 @@ struct process_t { bool system; - size_t code_selector; - size_t data_selector; - size_t physical_cr3; size_t paging_size; size_t physical_user_stack; size_t physical_kernel_stack; - size_t rip; - size_t user_rsp; size_t kernel_rsp; + interrupt::syscall_regs regs; + std::vector segments; std::vector physical_paging; }; diff --git a/kernel/include/scheduler.hpp b/kernel/include/scheduler.hpp index dd452147..d14d4ee8 100644 --- a/kernel/include/scheduler.hpp +++ b/kernel/include/scheduler.hpp @@ -16,7 +16,7 @@ namespace scheduler { void init(); void start(); -void kill_current_process(); +void kill_current_process(const interrupt::syscall_regs& regs); void reschedule(const interrupt::syscall_regs& regs); diff --git a/kernel/src/malloc.cpp b/kernel/src/malloc.cpp index d6af5c82..71726883 100644 --- a/kernel/src/malloc.cpp +++ b/kernel/src/malloc.cpp @@ -200,15 +200,25 @@ void init_head(){ malloc_head->prev_ref() = malloc_head; } -void expand_heap(malloc_header_chunk* current){ +void expand_heap(malloc_header_chunk* current, size_t bytes = 0){ + auto blocks = MIN_BLOCKS; + + if(bytes){ + auto necessary_blocks = ((bytes + META_SIZE) / BLOCK_SIZE) + 1; + + if(necessary_blocks > blocks){ + blocks = necessary_blocks; + } + } + //Allocate a new block of memory - uint64_t* block = allocate_block(MIN_BLOCKS); + uint64_t* block = allocate_block(blocks); //Transform it into a malloc chunk auto header = reinterpret_cast(block); //Update the sizes - header->size() = MIN_BLOCKS * BLOCK_SIZE - META_SIZE; + header->size() = blocks * BLOCK_SIZE - META_SIZE; header->footer()->size() = header->size(); //Insert the new block into the free list @@ -301,7 +311,7 @@ void* malloc::k_malloc(uint64_t bytes){ if(current == malloc_head){ //There are no blocks big enough to hold this request //So expand the heap - expand_heap(current); + expand_heap(current, bytes); } else if(current->size() >= bytes){ //This block is big enough diff --git a/kernel/src/scheduler.cpp b/kernel/src/scheduler.cpp index ea8a707d..4eb68983 100644 --- a/kernel/src/scheduler.cpp +++ b/kernel/src/scheduler.cpp @@ -45,19 +45,19 @@ void create_idle_task(){ idle_process.physical_user_stack = 0; idle_process.physical_kernel_stack = 0; - idle_process.rip = reinterpret_cast(&idle_task); - idle_process.user_rsp = reinterpret_cast(&idle_stack[63]); + idle_process.regs.rflags = 0x200; + idle_process.regs.rip = reinterpret_cast(&idle_task); + idle_process.regs.rsp = reinterpret_cast(&idle_stack[63]); idle_process.kernel_rsp = reinterpret_cast(&idle_kernel_stack[4095]); - idle_process.code_selector = gdt::LONG_SELECTOR; - idle_process.data_selector = gdt::DATA_SELECTOR; + idle_process.regs.cs = gdt::LONG_SELECTOR; + idle_process.regs.ds = gdt::DATA_SELECTOR; processes.push_back(std::move(idle_process)); rounds.push_back(0); } -void switch_to_process(size_t index) __attribute__((noreturn)); -void switch_to_process(size_t index){ +void switch_to_process(const interrupt::syscall_regs& regs, size_t index){ current_index = index; k_printf("Switched to %u\n", index); @@ -67,7 +67,29 @@ void switch_to_process(size_t index){ gdt::tss.rsp0_low = process.kernel_rsp & 0xFFFFFFFF; gdt::tss.rsp0_high = process.kernel_rsp >> 32; - asm volatile("mov rax, %0; mov ds, ax; mov es, ax; mov fs, ax; mov gs, ax;" + auto stack_pointer = reinterpret_cast(regs.placeholder); + + *(stack_pointer + 4) = process.regs.ds; + *(stack_pointer + 3) = process.regs.rsp; + *(stack_pointer + 2) = process.regs.rflags; + *(stack_pointer + 1) = process.regs.cs; + *(stack_pointer + 0) = process.regs.rip; + *(stack_pointer - 3) = process.regs.r12; + *(stack_pointer - 4) = process.regs.r11; + *(stack_pointer - 5) = process.regs.r10; + *(stack_pointer - 6) = process.regs.r9; + *(stack_pointer - 7) = process.regs.r8; + *(stack_pointer - 8) = process.regs.rdi; + *(stack_pointer - 9) = process.regs.rsi; + *(stack_pointer - 10) = process.regs.rdx; + *(stack_pointer - 11) = process.regs.rcx; + *(stack_pointer - 12) = process.regs.rbx; + *(stack_pointer - 13) = process.regs.rax; + *(stack_pointer - 14) = process.regs.ds; + + asm volatile("mov cr3, %0" : : "r" (process.physical_cr3) : "memory"); + + /*asm volatile("mov rax, %0; mov ds, ax; mov es, ax; mov fs, ax; mov gs, ax;" : //No outputs : "r" (process.data_selector) : "rax"); @@ -77,9 +99,7 @@ void switch_to_process(size_t index){ asm volatile("push %0; push %1; pushfq; pop rax; or rax, 0x200; push rax; push %2; push %3; iretq" : //No outputs : "r" (process.data_selector), "r" (process.user_rsp), "r" (process.code_selector), "r" (process.rip) - : "rax", "memory"); - - __builtin_unreachable(); + : "rax", "memory");*/ } size_t select_next_process(){ @@ -89,8 +109,7 @@ size_t select_next_process(){ void save_context(const interrupt::syscall_regs& regs){ auto& process = processes[current_index]; - process.user_rsp = regs.rsp; - process.rip = regs.rip; + process.regs = regs; } } //end of anonymous namespace @@ -105,10 +124,16 @@ void scheduler::start(){ started = true; - switch_to_process(processes.size() - 1); + current_index = 0; + rounds[current_index] = TURNOVER; + + //Wait for the next interrupt + while(true){ + asm volatile ("nop; nop; nop; nop"); + } } -void scheduler::kill_current_process(){ +void scheduler::kill_current_process(const interrupt::syscall_regs& regs){ k_printf("Kill %u\n", current_index); processes.erase(current_index); @@ -121,7 +146,7 @@ void scheduler::kill_current_process(){ //Select the next process and switch to it auto index = select_next_process(); - switch_to_process(index); + switch_to_process(regs, index); } void scheduler::reschedule(const interrupt::syscall_regs& regs){ @@ -141,7 +166,7 @@ void scheduler::reschedule(const interrupt::syscall_regs& regs){ save_context(regs); - switch_to_process(index); + switch_to_process(regs, index); } else { ++rounds[current_index]; } diff --git a/kernel/src/shell.cpp b/kernel/src/shell.cpp index c8fb9274..babe7629 100644 --- a/kernel/src/shell.cpp +++ b/kernel/src/shell.cpp @@ -809,7 +809,7 @@ bool create_paging(char* buffer, scheduler::process_t& process){ //2.1 Allocate user stack allocate_user_memory(process, scheduler::user_stack_start, scheduler::user_stack_size, process.physical_user_stack); - process.user_rsp = scheduler::user_rsp; + process.regs.rsp = scheduler::user_rsp; //2.2 Allocate all user segments @@ -865,22 +865,8 @@ bool create_paging(char* buffer, scheduler::process_t& process){ return true; } -void exec_command(const std::vector& params){ - if(params.size() < 2){ - k_print_line("exec: Need the name of the executable to read"); - - return; - } - - if(!disks::mounted_partition() || !disks::mounted_disk()){ - k_print_line("Nothing is mounted"); - - return; - } - - scheduler::init(); - - auto content = read_elf_file(params[1], "exec"); +void queue_process(const std::string& file){ + auto content = read_elf_file(file, "exec"); if(!content){ return; @@ -896,12 +882,34 @@ void exec_command(const std::vector& params){ return; } - process.rip = header->e_entry; + process.regs.rip = header->e_entry; - process.code_selector = gdt::USER_CODE_SELECTOR + 3; - process.data_selector = gdt::USER_DATA_SELECTOR + 3; + process.regs.cs = gdt::USER_CODE_SELECTOR + 3; + process.regs.ds = gdt::USER_DATA_SELECTOR + 3; + + process.regs.rflags = 0x200; scheduler::queue_process(std::move(process)); +} + +void exec_command(const std::vector& params){ + if(params.size() < 2){ + k_print_line("exec: Need the name of the executable to read"); + + return; + } + + if(!disks::mounted_partition() || !disks::mounted_disk()){ + k_print_line("Nothing is mounted"); + + return; + } + + scheduler::init(); + + for(size_t i = 1; i < params.size(); ++i){ + queue_process(params[i]); + } scheduler::start(); } diff --git a/kernel/src/system_calls.cpp b/kernel/src/system_calls.cpp index d8b0f206..95a3b2be 100644 --- a/kernel/src/system_calls.cpp +++ b/kernel/src/system_calls.cpp @@ -42,7 +42,7 @@ void system_call_entry(const interrupt::syscall_regs& regs){ break; case 0x666: - scheduler::kill_current_process(); + scheduler::kill_current_process(regs); break; default: diff --git a/programs/longone/Makefile b/programs/longone/Makefile new file mode 100644 index 00000000..be45dace --- /dev/null +++ b/programs/longone/Makefile @@ -0,0 +1,15 @@ +.PHONY: default clean + +default: a.out + +include ../../cpp.mk + +%.cpp.o: src/%.cpp + $(CC) $(PROGRAM_FLAGS) $(CPP_FLAGS_64) $(WARNING_FLAGS) -c $< -o $@ + +a.out: main.cpp.o + $(CC) $(PROGRAM_LINK_FLAGS) $(CPP_FLAGS_64) -o a.out main.cpp.o + +clean: + rm *.cpp.o + rm -rf a.out diff --git a/programs/longone/src/main.cpp b/programs/longone/src/main.cpp new file mode 100644 index 00000000..bb7dae1d --- /dev/null +++ b/programs/longone/src/main.cpp @@ -0,0 +1,30 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include + +volatile uint64_t current = 45; + +uint64_t fibonacci_slow(uint64_t s){ + if(s == 1 || s == 2){ + return current; + } + + return fibonacci_slow(s - 1) + fibonacci_slow(s - 2); +} + +auto message = "I'm one"; + +int main(){ + while(true){ + fibonacci_slow(current); + print_line(message); + } + + exit(0); +} \ No newline at end of file diff --git a/programs/longtwo/Makefile b/programs/longtwo/Makefile new file mode 100644 index 00000000..be45dace --- /dev/null +++ b/programs/longtwo/Makefile @@ -0,0 +1,15 @@ +.PHONY: default clean + +default: a.out + +include ../../cpp.mk + +%.cpp.o: src/%.cpp + $(CC) $(PROGRAM_FLAGS) $(CPP_FLAGS_64) $(WARNING_FLAGS) -c $< -o $@ + +a.out: main.cpp.o + $(CC) $(PROGRAM_LINK_FLAGS) $(CPP_FLAGS_64) -o a.out main.cpp.o + +clean: + rm *.cpp.o + rm -rf a.out diff --git a/programs/longtwo/src/main.cpp b/programs/longtwo/src/main.cpp new file mode 100644 index 00000000..9e502473 --- /dev/null +++ b/programs/longtwo/src/main.cpp @@ -0,0 +1,30 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include + +volatile uint64_t current = 45; + +uint64_t fibonacci_slow(uint64_t s){ + if(s == 1 || s == 2){ + return current; + } + + return fibonacci_slow(s - 1) + fibonacci_slow(s - 2); +} + +auto message = "I'm two"; + +int main(){ + while(true){ + fibonacci_slow(current); + print_line(message); + } + + exit(0); +} \ No newline at end of file