diff --git a/configure.ac b/configure.ac index 5739739..6ed9f7e 100644 --- a/configure.ac +++ b/configure.ac @@ -4,18 +4,17 @@ AC_PREREQ([2.69]) AC_INIT([quark-kernel], [pre-alpha]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) -AC_CONFIG_SRCDIR([src/allocator.cpp]) +AC_CONFIG_SRCDIR([src/kernel.c]) AC_CONFIG_HEADERS([src/config.h]) # Checks for programs. -AC_PROG_CXX AC_PROG_CC AM_PROG_AS AM_PROG_AR AC_PROG_RANLIB # Checks for header files. -AC_CHECK_HEADERS([stddef.h stdint.h]) +AC_CHECK_HEADERS([stddef.h stdint.h stdarg.h]) # Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 0000000..6605add --- /dev/null +++ b/include/elf.h @@ -0,0 +1,117 @@ +#pragma once + +#include "types/physaddr.h" +#include + +const uint32_t elf_magic_number = 0x464c457f; + +enum elf_endianness_t +{ + ELF_LITTLE_ENDIAN = 1, + ELF_BIG_ENDIAN = 2 +}; + +enum elf_isa_t +{ + ELF_ISA_NA = 0x00, + ELF_ISA_x86 = 0x03, + ELF_ISA_MIPS = 0x08, + ELF_ISA_PPC = 0x14, + ELF_ISA_PPC64 = 0x15, + ELF_ISA_ARM = 0x28, + ELF_ISA_x86_64 = 0x3E, + ELF_ISA_AARCH64 = 0xB7 +}; + +enum elf_segment_type_t +{ + ELF_UNUSED = 0, + ELF_LOAD = 1, + ELF_DYNAMIC = 2 +}; + +struct elf_file_header_t +{ + uint32_t magic; + char size; + char endianness; + char version; + char abi; + char abi_version; + char reserved[7]; + uint16_t type; + uint16_t machine; + uint32_t _version; + void *entry; +#if defined __i386__ || defined __arm__ + uint32_t phoffset; + uint32_t shoffset; +#elif defined __x86_64__ || defined __aarch64__ + uint64_t phoffset; + uint64_t shoffset; +#endif + uint32_t flags; + uint16_t header_size; + uint16_t phsize; + uint16_t phcount; + uint16_t shsize; + uint16_t shcount; + uint16_t shstrndx; +}; + +struct elf_program_header_t +{ + uint32_t type; +#if defined __i386__ || defined __arm__ + uint32_t offset; + void *vaddr; + physaddr_t paddr; + uint32_t filesize; + uint32_t memsize; + uint32_t flags; + uint32_t align; +#elif defined __x86_64__ || defined __aarch64__ + uint32_t flags; + uint64_t offset; + void *vaddr; + physaddr_t paddr; + uint64_t filesize; + uint64_t memsize; + uint64_t align; +#endif +}; + +struct elf_section_header_t +{ + uint32_t name; + uint32_t type; +#if defined __i386__ || defined __arm__ + uint32_t flags; + void *addr; + uint32_t offset; + uint32_t size; + uint32_t link; + uint32_t info; + uint32_t align; + uint32_t entry_size; +#elif defined __x86_64__ || defined __aarch64__ + uint64_t flags; + void *addr; + uint64_t offset; + uint64_t size; + uint32_t link; + uint32_t info; + uint64_t align; + uint64_t entry_size; +#endif +}; + +#if defined __i386__ + static const elf_isa_t HOST_ISA = ELF_ISA_x86; +#elif defined __x86_64__ + static const elf_isa_t HOST_ISA = ELF_ISA_x86_64; +#elif defined __arm__ + static const elf_isa_t HOST_ISA = ELF_ISA_ARM; +#elif defined __aarch64__ + static const elf_isa_t HOST_ISA = ELF_ISA_AARCH64; +#endif diff --git a/include/kernel.h b/include/kernel.h new file mode 100644 index 0000000..9f6da99 --- /dev/null +++ b/include/kernel.h @@ -0,0 +1,18 @@ +#pragma once + +#include "priorityqueue.h" +#include "module.h" +#include + +struct kernel_t +{ + struct priority_queue_t *priority_queue; +}; + +extern struct kernel_t kernel; + +int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3); + +int load_module(struct kernel_t *kernel, struct module_t *module); + +void panic(const char *message) __attribute__ ((noreturn)); diff --git a/include/memorymap.h b/include/memorymap.h new file mode 100644 index 0000000..933b641 --- /dev/null +++ b/include/memorymap.h @@ -0,0 +1,27 @@ +#pragma once + +#include "types/physaddr.h" +#include + +enum memory_type_t +{ + M_AVAILABLE = 1, + M_UNAVAILABLE = 2, + M_DEFECTIVE = 3 +}; + +struct memory_region_t +{ + physaddr_t location; + size_t size; + unsigned int type; +}; + +struct memory_map_t +{ + struct memory_region_t *array; + size_t size; + size_t capacity; +}; + +void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, enum memory_type_t type); \ No newline at end of file diff --git a/include/mmgr.h b/include/mmgr.h new file mode 100644 index 0000000..dc80161 --- /dev/null +++ b/include/mmgr.h @@ -0,0 +1,39 @@ +#pragma once + +#include "pageallocator.h" +#include "types/physaddr.h" + +/** + * @brief Create a new top-level page table and map the kernel in it. + * + * This function does not load the page table; it only initializes it. + * + * @return physaddr_t + */ +physaddr_t create_address_space(struct page_stack_t *page_stack); + +/** + * @brief Load an existing top-level page table + * + * @param table + */ +void load_address_space(physaddr_t table); + +/** + * @brief Maps a single page with the specified flags. + * + * @param page + * @param frame + * @param flags + * @return int + */ +int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags); + +/** + * @brief Unmaps a single page, returning the physical address of the frame it + * pointed to. + * + * @param page + * @return physaddr_t + */ +physaddr_t unmap_page(void *page); \ No newline at end of file diff --git a/include/module.h b/include/module.h new file mode 100644 index 0000000..4e0cc1a --- /dev/null +++ b/include/module.h @@ -0,0 +1,10 @@ +#pragma once + +#include "types/physaddr.h" + +struct module_t +{ + physaddr_t start; + physaddr_t end; + char str[64 - 2 * sizeof(physaddr_t)]; +}; \ No newline at end of file diff --git a/include/pageallocator.h b/include/pageallocator.h new file mode 100644 index 0000000..5b52d54 --- /dev/null +++ b/include/pageallocator.h @@ -0,0 +1,75 @@ +#pragma once + +#include "memorymap.h" +#include "types/physaddr.h" +#include + +/** + * @brief Describes a stack containing the physical addresses of available page + * frames. + * + */ +struct page_stack_t +{ + /** + * @brief The total number of physical pages managed by the system. + * + */ + size_t total_pages; + + /** + * @brief Points to the topmost physical address on the stack. + * + */ + physaddr_t *stack_pointer; + + /** + * @brief Points to the bottom of the stack. + * + */ + physaddr_t *base_pointer; + + /** + * @brief Points to the limit of the stack. The stack cannot grow beyond + * this point. + * + */ + physaddr_t *limit_pointer; +}; + +/** + * @brief Pop the topmost address from the stack and returns that value. + * + * If the stack is empty, this function will instead return a status code. This + * can be identified by testing the least signifigant bits of the return value. + * + * @param stack + * @return physaddr_t + */ +physaddr_t reserve_page(struct page_stack_t *stack); + +/** + * @brief Pushes `location` onto the stack. + * + * If there is no room on the stack, the stack will be unaffected. + * + * @param stack + * @param location + */ +int free_page(struct page_stack_t *stack, physaddr_t location); + +/** + * @brief Computes the number of available pages. + * + * @param stack + * @return size_t + */ +size_t free_page_count(struct page_stack_t *stack); + +/** + * @brief Push all available pages in `map` onto the stack + * + * @param stack + * @param map + */ +int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size); diff --git a/include/priorityqueue.h b/include/priorityqueue.h new file mode 100644 index 0000000..85aed7a --- /dev/null +++ b/include/priorityqueue.h @@ -0,0 +1,55 @@ +#pragma once + +#include "process.h" +#include + +/** + * @brief + * + */ +struct priority_queue_t +{ + /** + * @brief A pointer to the heap described by this structure. + * + */ + struct process_t **heap; + + /** + * @brief The current number of elements stored in the heap. + * + */ + size_t size; + + /** + * @brief The maximum number of elements that the heap can currently hold. + * + */ + size_t capacity; +}; + +/** + * @brief + * + * @param queue + * @return struct process_t* + */ +struct process_t *extract_min(struct priority_queue_t *queue); + +/** + * @brief + * + * @param queue + * @param process + * @return int + */ +int insert(struct priority_queue_t *queue, struct process_t *process); + +/** + * @brief + * + * @param queue + * @param process + * @return int + */ +int remove(struct priority_queue_t *queue, struct process_t *process); diff --git a/include/process.h b/include/process.h new file mode 100644 index 0000000..be2bdbf --- /dev/null +++ b/include/process.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +struct process_state_t; + +struct process_t +{ + size_t priority; + + struct process_state_t *state; +}; \ No newline at end of file diff --git a/include/stdio.h b/include/stdio.h new file mode 100644 index 0000000..3c086ee --- /dev/null +++ b/include/stdio.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +int putchar(int c); + +int puts(const char *str); + +int printf(const char *format, ...); + +int sprintf(char *str, const char *format, ...); \ No newline at end of file diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..459eea8 --- /dev/null +++ b/include/string.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +void *memcpy(void *destination, const void *source, size_t num); + +void *memmove(void *destination, const void *source, size_t num); + +int memcmp(const void *ptr1, const void *ptr2, size_t num); + +void *memset(void *ptr, int value, size_t num); + +int strlen(const char *str); + +char *strcpy(char *destination, const char *source); diff --git a/src/types/physaddr.h b/include/types/physaddr.h similarity index 74% rename from src/types/physaddr.h rename to include/types/physaddr.h index 5cd2f26..fb00318 100644 --- a/src/types/physaddr.h +++ b/include/types/physaddr.h @@ -1,8 +1,6 @@ -#ifndef PHYSADDR_H -#define PHYSADDR_H +#pragma once #include -#include #if defined __i386__ || __arm__ typedef uint32_t physaddr_t; @@ -10,6 +8,4 @@ typedef uint32_t physaddr_t; typedef uint64_t physaddr_t; #else typedef uint64_t physaddr_t; -#endif - #endif \ No newline at end of file diff --git a/include/types/status.h b/include/types/status.h new file mode 100644 index 0000000..232f39b --- /dev/null +++ b/include/types/status.h @@ -0,0 +1,9 @@ +#pragma once + +enum status_t +{ + S_OK = 0, + S_BAD_SYSCALL, + S_OUT_OF_MEMORY, + S_OUT_OF_BOUNDS +}; \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index b4709fc..e696654 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,15 +1,18 @@ noinst_PROGRAMS = quark-kernel -quark_kernel_SOURCES = module.cpp util.cpp memorymap.cpp memoryregion.cpp pageallocator.cpp allocator.cpp scheduler.cpp +quark_kernel_SOURCES = kernel.c memorymap.c pageallocator.c priorityqueue.c stdio.c string.c quark_kernel_LDADD = -lgcc -quark_kernel_CPPFLAGS = -ffreestanding -mgeneral-regs-only -O0 -Wall -fno-exceptions -fno-rtti -ggdb +quark_kernel_CFLAGS = -I$(top_srcdir)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb quark_kernel_LDFLAGS = -nostdlib if x86 -quark_kernel_SOURCES += x86/mmap.cpp \ - x86/tty.cpp \ - x86/interrupts.cpp \ - x86/multiboot2.cpp \ - x86/initialize.cpp \ +quark_kernel_SOURCES += x86/mmgr.c \ + x86/putc.c \ + x86/multiboot2.c \ + x86/interrupts.c \ + x86/apic.c \ + x86/isr.c \ + x86/msr.c \ + x86/quark_x86.c \ x86/entry.S quark_kernel_LDFLAGS += -T x86/linker.ld quark_kernel_DEPENDENCIES = x86/linker.ld diff --git a/src/elf.cpp b/src/elf.cpp deleted file mode 100644 index 503da94..0000000 --- a/src/elf.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "elf.hpp" -#include "util.hpp" - -kernelns::ELF::ELF() -{ - this->m_fileLocation = (void*) NULL; -} - -kernelns::ELF::ELF(void* location) -{ - this->m_fileLocation = location; -} - -void* kernelns::ELF::entry() -{ - Header* fileHeader = (Header*) m_fileLocation; - return fileHeader->entry; -} - -int kernelns::ELF::validate() -{ - Header* fileHeader = (Header*) m_fileLocation; - if(fileHeader->magic != 0x464c457f) - return -1; - else if((ISA) fileHeader->machine != HOST_ISA) - return -1; - else if((Endianness) fileHeader->endianness != Little) - return -1; - return 0; -} - -int kernelns::ELF::load() -{ - Header* fileHeader = (Header*) m_fileLocation; - ProgramHeader* programHeader = (ProgramHeader*) ((size_t) m_fileLocation + fileHeader->phoffset); - int count = (int) fileHeader->phcount; - for(int i = 0; i < count; i++) - { - if((SegmentType) programHeader->type != Load) - continue; - memcpy(programHeader->vaddr, m_fileLocation + programHeader->offset, programHeader->filesize); - } - return 0; -} \ No newline at end of file diff --git a/src/elf.hpp b/src/elf.hpp deleted file mode 100644 index be986e6..0000000 --- a/src/elf.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef ELF_H -#define ELF_H - -#include "systypes.hpp" - -namespace kernelns -{ - -class ELF -{ -public: - - enum Endianness - { - Little = 1, - Big = 2 - }; - - enum ISA - { - NA = 0x00, - x86 = 0x03, - MIPS = 0x08, - PPC = 0x14, - PPC64 = 0x15, - ARM = 0x28, - x86_64 = 0x3E, - aarch64 = 0xB7 - }; - - enum SegmentType - { - Unused = 0, - Load = 1, - Dynamic = 2 - }; - - struct Header - { - uint32_t magic; - char size; - char endianness; - char version; - char abi; - char abiVersion; - char reserved[7]; - uint16_t type; - uint16_t machine; - uint32_t _version; - void* entry; -#if defined __i386__ || defined __arm__ - uint32_t phoffset; - uint32_t shoffset; -#elif defined __x86_64__ || defined __aarch64__ - uint64_t phoffset; - uint64_t shoffset; -#endif - uint32_t flags; - uint16_t headerSize; - uint16_t phsize; - uint16_t phcount; - uint16_t shsize; - uint16_t shcount; - uint16_t shstrndx; - }; - - struct ProgramHeader - { - uint32_t type; -#if defined __i386__ || defined __arm__ - uint32_t offset; - void* vaddr; - physaddr_t paddr; - uint32_t filesize; - uint32_t memsize; - uint32_t flags; - uint32_t align; -#elif defined __x86_64__ || defined __aarch64__ - uint32_t flags; - uint64_t offset; - void* vaddr; - physaddr_t paddr; - uint64_t filesize; - uint64_t memsize; - uint64_t align; -#endif - }; - - struct SectionHeader - { - uint32_t name; - uint32_t type; -#if defined __i386__ || defined __arm__ - uint32_t flags; - void* addr; - uint32_t offset; - uint32_t size; - uint32_t link; - uint32_t info; - uint32_t align; - uint32_t entrysize; -#elif defined __x86_64__ || defined __aarch64__ - uint64_t flags; - void* addr; - uint64_t offset; - uint64_t size; - uint32_t link; - uint32_t info; - uint64_t align; - uint64_t entrysize; -#endif - }; - -#if defined __i386__ - static const ISA HOST_ISA = x86; -#elif defined __x86_64__ - static const ISA HOST_ISA = x86_64; -#elif defined __arm__ - static const ISA HOST_ISA = ARM; -#elif defined __aarch64__ - static const ISA HOST_ISA = aarch64; -#endif - - ELF(); - - ELF(void* location); - - void* entry(); - - int validate(); - - int load(); - -private: - - void* m_fileLocation; - -}; - -} - -#endif \ No newline at end of file diff --git a/src/heap.hpp b/src/heap.hpp deleted file mode 100644 index cf6b456..0000000 --- a/src/heap.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef SCHEDULER_H -#define SCHEDULER_H - -#include - -#include "process.hpp" - -namespace kernelns -{ - -template -class Heap -{ -public: - - Heap() - { - - } - - Heap(T** array, size_t maxSize) - { - m_array = array; - m_size = 0; - m_limit = maxSize; - } - - T* extractMin() - { - if(m_size == 0) - return nullptr; - m_size--; - T* p = m_array[0]; - m_array[0] = m_array[m_size]; - heapify(0); - return p; - } - - Status insert(T* n) - { - if(m_size == m_limit) - return Status::NoMemory; - size_t i = m_size; - m_size++; - while(i > 0 && *m_array[(i - 1) / 2] > *n) - { - m_array[i] = m_array[(i - 1) / 2]; - i = (i - 1) / 2; - } - m_array[i] = n; - return Status::OK; - } - - void remove(T* n) - { - for(size_t i = 0; i < m_size; i++) - { - if(m_array[i] == n) - { - m_size--; - m_array[i] = m_array[m_size]; - heapify(i); - break; - } - } - } - -private: - - void heapify(size_t index) - { - if(i * 2 + 1 >= m_size) - return; - if (*m_array[i * 2 + 1] <= *m_array[i] && *m_array[i * 2 + 1] <= *m_array[i * 2 + 2]) - { - T buffer = m_array[i]; - m_array[i] = m_array[i * 2 + 1]; - m_array[i * 2 + 1] = buffer; - heapify(i * 2 + 1); - } - else if (*m_array[i * 2 + 2] <= *m_array[i] && *m_array[i * 2 + 2] <= *m_array[i * 2 + 1]) - { - T buffer = m_array[i]; - m_array[i] = m_array[i * 2 + 2]; - m_array[i * 2 + 2] = buffer; - heapify(i * 2 + 2); - } - } - - T** m_array; - - size_t m_size, m_limit; - -}; - -}; - -#endif \ No newline at end of file diff --git a/src/interrupts.hpp b/src/interrupts.hpp deleted file mode 100644 index f8c99aa..0000000 --- a/src/interrupts.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef INTERRUPTS_H -#define INTERRUPTS_H - -namespace kernelns -{ - class Interrupts - { - public: - - static const unsigned int MAX_SYSCALL_ID = 31; - - Interrupts(); - - void enable(); - - void disable(); - - void addSyscall(unsigned int id, void* function); - - private: - - void* syscalls[MAX_SYSCALL_ID + 1]; - - }; -} - -#endif \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 0000000..cf049dc --- /dev/null +++ b/src/kernel.c @@ -0,0 +1,11 @@ +#include "kernel.h" + +int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3) +{ + +} + +int load_module(struct kernel_t *kernel, struct module_t *module) +{ + +} \ No newline at end of file diff --git a/src/kernel.cpp b/src/kernel.cpp deleted file mode 100644 index 98795ff..0000000 --- a/src/kernel.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "kernel.hpp" - -int Kernel::allocateRegion(void* page, size_t length, int flags) -{ - char* ptr = (char*) page; - for(int i = (int) length; i > 0; i -= mmgr.getPageSize()) - { - physaddr_t frame = pageAllocator.allocate(mmgr.getPageSize()); - if(frame != 0) - mmgr.mapPage(page, reserveFrame(), flags); - else - return -1; - ptr += mmgr.getPageSize(); - } - return 0; -} - -void Kernel::freeRegion(void* page, size_t length) -{ - char* ptr = (char*) page; - for(int i = (int) length; i > 0; i -= mmgr.getPageSize()) - { - pageAllocator.free(mmgr.unmapPage((void*) ptr), mmgr.getPageSize()); - ptr += mmgr.getPageSize(); - } -} - -int Kernel::mapRegion(void* page, physaddr_t frame, size_t length, int flags) -{ - -} \ No newline at end of file diff --git a/src/kernel.hpp b/src/kernel.hpp deleted file mode 100644 index 700989a..0000000 --- a/src/kernel.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef KERNEL_H -#define KERNEL_H - -#include "pageallocator.hpp" -#include "memorymanager.hpp" -#include "memorymap.hpp" -#include "sharedblock.hpp" -#include "process.hpp" -#include "systypes.hpp" - -using namespace kernelns; - -class Kernel -{ -public: - - void* malloc(size_t size); - - void free(void* ptr); - - /** - * @brief Maps a region of pages starting at virtual address 'page' with - * length 'length'. Allocates each mapped frame and any necessary page - * tables. This method does not perform any checks before overwriting page - * tables; it is the responsibility of the caller to ensure that the - * operation is safe to perform. - * - * @param page The virtual address of the first page to map - * @param length The size in bytes of the region to map - * @param flags The flags to apply to each page - * - * @returns zero upon success, nonzero on failure - */ - int allocateRegion(void* page, size_t length, int flags); - - /** - * @brief Unmaps and frees a region of mapped pages starting at virtual - * address 'page' with length 'length'. Does not free any page tables - * that are made redundant by this operation. It is the responsibility - * of the caller to ensure that all pages in the specified region are - * mapped and should be returned to the page allocator. - * - * @param page The virtual address of the first page to free - * @param length The size in bytes of the region to free - */ - void freeRegion(void* page, size_t length); - - /** - * @brief Maps a contiguous region of pages to a contiguous region of - * frames. Allocates new page tables as needed. All pages will share - * the same flags. - * - * @param page The virtual address of the first page to map - * @param frame The physical address of the first frame to map to - * @param length The size in bytes of the region to map - * @param flags The flags to apply to each page - * - * @returns zero upon success, nonzero on failure - */ - int mapRegion(void* page, physaddr_t frame, size_t length, int flags); - - /** - * @brief Unmaps a region of pages; does not return them to the page - * allocator. - * - * @param page The virtual address of the first page to unmap - * @param length The size in bytes of the region to unmap - */ - void unmapRegion(void* page, size_t length); - - /** - * @brief Create a Shared Block object - * - * @param length - * @param flags - * @returns The ID of the - */ - unsigned int createSharedBlock(size_t length, int flags); - - /** - * @brief Get the shared memory block referred to by 'id' - * - * @param id - * @returns a reference - */ - const SharedBlock& getSharedBlock(unsigned int id); - - /** - * @brief Create a new process - * - * @param imageBlockID - * @return Process& - */ - Process& createProcess(unsigned int imageBlockID); - - /** - * @brief Get the process object corresponsing to 'pid' - * - * @param pid id of the process to fetch - * @returns a reference to the requested process - */ - Process& getProcess(unsigned int pid); - - /** - * @brief Get the current active process object. - * - * @returns a reference to the active process - */ - Process& getActiveProcess(); - - /** - * @brief Puts the current active process back on the run queue, and sets - * the active process to the next one selected by the scheduler. - * - * @returns a reference to the new active process - */ - Process& yieldActiveProcess(); - - /** - * @brief Puts the current active process to sleep, and sets the active - * process to the next one selected by the scheduler. - * - * @returns a reference to the new active process - */ - Process& sleepActiveProcess(); - - /** - * @brief Terminates the current active process, freeing all its resources, - * and activates the next process selected by the scheduler. - * - * @return Process& - */ - Process& terminateActiveProcess(); - - /** - * @brief Terminates the process with id 'pid', freeing all its resources. - * If it holds any shared blocks which are not held by any other process, - * those blocks will be freed. - * - * @param pid id of the process to terminate - */ - void terminateProcess(unsigned int pid); - -private: - - PageAllocator& pageAllocator; - - MemoryManager& mmgr; - - MemoryMap& memoryMap; - -}; - -extern Kernel kernel; - -#endif \ No newline at end of file diff --git a/src/memorymanager.hpp b/src/memorymanager.hpp deleted file mode 100644 index 72d8237..0000000 --- a/src/memorymanager.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef MEMORYMANAGER_H -#define MEMORYMANAGER_H - -#include "systypes.hpp" - -class MemoryManager -{ -public: - - /** - * @brief Returns the size of a single page on the present platform. - * - * @return the size in bytes of a single page - */ - virtual unsigned int getPageSize() const = 0; - - /** - * Allocates space for a new top-level page table, and initializes it to - * point only to the kernel's page tables. - * - * @returns the physical address of the new top-level page table - */ - virtual physaddr_t createAddressSpace() = 0; - - /** - * Loads the given top-level page table(s). - * - * @param table the top-level page table to load - */ - virtual void loadAddressSpace(physaddr_t table) = 0; - - /** - * Maps a single page to a single frame. Allocates a new page table if one - * does not exist for that frame. - * - * @param page the virtual address of the page to map - * @param frame the physical address of the frame to map to - * @param flags flags to apply to the entry - * - * @returns zero upon success, nonzero on failure - */ - virtual int mapPage(void* page, physaddr_t frame, int flags) = 0; - - /** - * Deletes the page table entry for the specified page. Does not deallocate - * redundant page tables or modify higher level tables; these are cleaned up - * after the owning process ends. - * - * @param page the virtual address of the page to unmap - */ - virtual physaddr_t unmapPage(void* page) = 0; - -}; - -#endif \ No newline at end of file diff --git a/src/memorymap.c b/src/memorymap.c new file mode 100644 index 0000000..2adef20 --- /dev/null +++ b/src/memorymap.c @@ -0,0 +1,136 @@ +#include "memorymap.h" +#include + +int compare_regions(struct memory_region_t *lhs, struct memory_region_t *rhs) +{ + if(lhs->location == rhs->location) + { + return lhs->size > rhs->size ? 1 + : (lhs->size == rhs->size ? 0 + : -1); + } + else + { + return lhs->location > rhs->location ? 1 : -1; + } +} + +bool region_overlaps(struct memory_region_t *lhs, struct memory_region_t *rhs) +{ + if(rhs->location < lhs->location) + { + return rhs->location + rhs->size > lhs->location; + } + return rhs->location < lhs->location + lhs->size; +} + +bool region_contains(struct memory_region_t *lhs, struct memory_region_t *rhs) +{ + return (rhs->location >= lhs->location) && + (rhs->location + rhs->size <= lhs->location + lhs->size); +} + +void insert_map_entry(struct memory_map_t *map, physaddr_t location, size_t size, unsigned int type) +{ + struct memory_region_t new_region = {.location = location, .size = size, .type = type}; + unsigned int i = 0; + while(i < map->size) + { + if(compare_regions(&new_region, &map->array[i]) < 0) + { + struct memory_region_t buffer = new_region; + new_region = map->array[i]; + map->array[i] = buffer; + } + i++; + } + map->array[i] = new_region; + map->size++; +} + +void remove_map_entry(struct memory_map_t *map, int index) +{ + if(index >= 0 && index < map->size) + { + for(int i = index; i < map->size - 1; i++) + { + map->array[i] = map->array[i + 1]; + } + map->size--; + } +} + +int trim_map(struct memory_map_t *map, int index) +{ + if(index + 1 >= map->size) + { + return -1; + } + struct memory_region_t left = map->array[index]; + struct memory_region_t right = map->array[index + 1]; + if(region_overlaps(&left, &right)) + { + if(left.type == right.type) + { + left.size = (right.location + right.size > left.location + left.size ? right.location + right.size : left.location + left.size) - left.location; + remove_map_entry(map, index + 1); + return index; + } + else if(left.type < right.type) + { + if(region_contains(&right, &left)) + { + remove_map_entry(map, index); + return index; + } + else if(left.location + left.size <= right.location + right.size) + { + left.size = (right.location > left.location) ? right.location - left.location : 0; + return index + 1; + } + else + { + struct memory_region_t new_right = { + .location = right.location + right.size, + .size = (left.location + left.size) - (right.location + right.size), + .type = left.type}; + left.size = (right.location > left.location) ? right.location - left.location : 0; + if(left.size == 0) + remove_map_entry(map, index); + insert_map_entry(map, new_right.location, new_right.size, new_right.type); + return index + 2; + } + } + else + { + if(region_contains(&left, &right)) + { + remove_map_entry(map, index + 1); + return index; + } + else + { + right.size = (right.location + right.size) - (left.location + left.size); + right.location = left.location + left.size; + return index + 1; + } + } + } + else if((left.location + left.size == right.location) && left.type == right.type) + { + left.size = right.location + right.size - left.location; + remove_map_entry(map, index + 1); + return index; + } + return index + 1; +} + +void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, unsigned int type) +{ + insert_map_entry(map, location, size, type); + int i = 0; + while(i >= 0) + { + i = trim_map(map, i); + } +} \ No newline at end of file diff --git a/src/memorymap.cpp b/src/memorymap.cpp deleted file mode 100644 index e1b21e9..0000000 --- a/src/memorymap.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "memorymap.hpp" - -using namespace kernelns; - -MemoryMap::MemoryMap() -{ - this->m_entries = 0; -} - -MemoryMap::MemoryMap(MemoryMap& copy) -{ - for(int i = 0; i < copy.m_entries; i++) - m_map[i] = copy[i]; - this->m_entries = copy.m_entries; -} - -const MemoryRegion& MemoryMap::operator[](size_t index) const -{ - return m_map[index]; -} - -size_t MemoryMap::size() const -{ - return m_entries; -} - -size_t MemoryMap::totalMemory() const -{ - size_t sum = 0; - for(int i = 0; i < m_entries; i++) - { - sum += m_map[i].getSize(); - } - return sum; -} - -size_t MemoryMap::totalMemory(unsigned int type) const -{ - size_t sum = 0; - for(int i = 0; i < m_entries; i++) - { - if(m_map[i].getType() == type) - sum += m_map[i].getSize(); - } - return sum; -} - -bool MemoryMap::overlaps(const MemoryRegion& region) const -{ - for(int i = 0; i < m_entries; i++) - { - if(m_map[i].overlaps(region)) - return true; - } - return false; -} - -bool MemoryMap::contains(const MemoryRegion& region) const -{ - for(int i = 0; i < m_entries; i++) - { - if(m_map[i].contains(region) && m_map[i].getType() == region.getType()) - return true; - } - return false; -} - -void MemoryMap::insertEntry(const MemoryRegion& region) -{ - simpleInsert(region); - unsigned int i = 0; - while(i != invalidIndex) - i = trim(i); -} - -void MemoryMap::insertEntry(physaddr_t location, size_t size, unsigned int type) -{ - insertEntry(MemoryRegion(location, size, type)); -} - -void MemoryMap::remove(unsigned int index) -{ - for(unsigned int i = index; i < (m_entries - 1); i++) - { - m_map[i] = m_map[i+1]; - } - m_entries--; -} - -void MemoryMap::simpleInsert(const MemoryRegion& region) -{ - MemoryRegion newRegion(region); - unsigned int i = 0; - while(i < m_entries) - { - if(newRegion < m_map[i]) - { - MemoryRegion buffer = newRegion; - newRegion = m_map[i]; - m_map[i] = buffer; - } - i++; - } - m_map[i] = newRegion; - m_entries++; -} - -void MemoryMap::simpleInsert(physaddr_t location, size_t size, unsigned int type) -{ - simpleInsert(MemoryRegion(location, size, type)); -} - -unsigned int MemoryMap::trim(unsigned int index) -{ - if(index + 1 >= m_entries) - return invalidIndex; - MemoryRegion& left = m_map[index]; - MemoryRegion& right = m_map[index+1]; - if(left.overlaps(right)) - { - if(left.getType() == right.getType()) - { - left = MemoryRegion(left.getLocation(), - (right.getEnd() > left.getEnd() ? right.getEnd() : left.getEnd()) - left.getLocation(), - left.getType()); - remove(index + 1); - return index; - } - else if(left.getType() < right.getType()) - { - if(right.contains(left)) - { - remove(index); - return index; - } - else if(left.getEnd() <= right.getEnd()) - { - left.truncateRight(right.getLocation()); - return index + 1; - } - else - { - MemoryRegion newRight(right.getEnd(), left.getEnd() - right.getEnd(), left.getType()); - left.truncateRight(right.getLocation()); - if(left.getSize() == 0) - remove(index); - simpleInsert(newRight); - return index + 2; - } - } - else - { - if(left.contains(right)) - { - remove(index + 1); - return index; - } - else - { - right.truncateLeft(left.getEnd()); - return index + 1; - } - } - } - else if(left.bordersLeft(right) && left.getType() == right.getType()) - { - left = MemoryRegion(left.getLocation(), right.getEnd() - left.getLocation(), left.getType()); - remove(index + 1); - return index; - } - return index + 1; -} \ No newline at end of file diff --git a/src/memorymap.hpp b/src/memorymap.hpp deleted file mode 100644 index 6c428af..0000000 --- a/src/memorymap.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef MEMORYMAP_H -#define MEMORYMAP_H - -#include "systypes.hpp" -#include "memoryregion.hpp" - -namespace kernelns -{ - -class MemoryMap -{ -public: - - MemoryMap(); - - MemoryMap(MemoryMap& copy); - - const MemoryRegion& operator[](size_t index) const; - - /** - * @return The number of memory regions described by this object - */ - size_t size() const; - - /** - * @brief Get the total amount of memory described by this memory map. - * Since no two regions may overlap, this is equivalent to the sum of the - * size of each memory region stored in this object. - * - * @return The total amount of memory described by this memory map. - */ - size_t totalMemory() const; - - /** - * @brief Get the total amount of memory of a specified type described by - * this memory map. Since no two regions overlap, this is equivalent to the - * sum of the size of each memory region stored in this object whose type - * is equal to `type`. - * - * @param type The type of memory region to count - * @return The total amount of memory of the specified type - */ - size_t totalMemory(unsigned int type) const; - - /** - * @brief Checks if `region` overlaps any memory region contained in this - * memory map. - * - * @param region - * @return true if, for any region `k` in this map, `k.overlaps(region)`. - * @return false if there is no region in this map where `k.overlaps(region)`. - */ - bool overlaps(const MemoryRegion& region) const; - - /** - * @brief Checks if `region` is contained an any memory region in this map - * with the same type as `region`. - * - * @param region - * @return true if, for any region `k` in this map, `k.contains(region) - * && k.getType() == region.getType()`. - * @return false if the condition above is not true - */ - bool contains(const MemoryRegion& region) const; - - /** - * @brief Adds `region` into the memory map. Adjusts the map as necessary - * so that no regions overlap. Regions of higher type take precedence over - * regions with lower types; therefore, the lower typed regions are trimmed - * or deleted where they overlap with higher typed regions. Adjacent or - * overlapping regions with identical types are merged. - * - * @param region The memory region to insert - */ - void insertEntry(const MemoryRegion& region); - - /** - * @brief Overload of `insertEntry()`. @see insertRegion(const MemoryRegion&). - * - * @param location - * @param size - * @param type - */ - void insertEntry(physaddr_t location, size_t size, unsigned int type); - -private: - - /** - * @brief Removes the element at `index` in `m_map`. All objects located - * after that index are moved accordingly. - * - * @param index Locatation of the object to delete - */ - void remove(unsigned int index); - - /** - * @brief Inserts a copy of `region` into `m_map`. The new element is - * inserted such that `m_map` is sorted in ascending order. Overlapping - * elements are not trimmed. - * - * @param region The memory region to insert - */ - void simpleInsert(const MemoryRegion& region); - - /** - * @brief Overload of `simpleInsert(const MemoryRegion& region)`. - * - * @param location - * @param size - * @param type - */ - void simpleInsert(physaddr_t location, size_t size, unsigned int type); - - /** - * @brief If `m_map[index].overlaps(m_map[index+1])`, the two elements are - * modified so that they no longer overlap. The following rules apply: - * - * 1. This memory map will describe the same set of locations before and - * after performing this operation. - * - * 2. Adjacent regions of the same type are merged into a single region. - * - * 3. Where two regions of differing types overlap, the higher type takes - * precedence. The region of the lower type is truncated, split, or deleted - * so as to not overlap the region of the higher type. - * - * 4. This operation is local: only `m_map[index]` and `m_map[index+1]` are - * modified (although if a region must be split, a new region will be - * inserted at the location `index+2`). - * - * This function has no effect if `index+1 >= m_entries`, or if - * `m_map[index]` does not overlap the `m_map[index+1]`. - * - * @param index The location of the region to trim. - * - * @return The index of the rightmost region affected. - */ - unsigned int trim(unsigned int index); - - static const unsigned int maxEntries = 16; - - static const unsigned int invalidIndex = 0xFFFF; - - MemoryRegion m_map[maxEntries]; - - size_t m_entries; - -}; - -} - -#endif \ No newline at end of file diff --git a/src/memoryregion.cpp b/src/memoryregion.cpp deleted file mode 100644 index d0eeb15..0000000 --- a/src/memoryregion.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "memoryregion.hpp" - -MemoryRegion::MemoryRegion() -{ - m_location = 0; - m_size = 0; - m_type = 0; -} - -MemoryRegion::MemoryRegion(const MemoryRegion& copy) -{ - m_location = copy.m_location; - m_size = copy.m_size; - m_type = copy.m_type; -} - -MemoryRegion::MemoryRegion(physaddr_t location, size_t size, unsigned int type) -{ - m_location = location; - m_size = size; - m_type = (size_t) type; -} - -const MemoryRegion& MemoryRegion::operator=(const MemoryRegion& rhs) -{ - m_location = rhs.m_location; - m_size = rhs.m_size; - m_type = rhs.m_type; - return rhs; -} - -bool MemoryRegion::operator==(const MemoryRegion& rhs) const -{ - return (m_location == rhs.m_location) && (m_size == rhs.m_size); -} - -bool MemoryRegion::operator!=(const MemoryRegion& rhs) const -{ - return (m_location != rhs.m_location) || (m_size != rhs.m_size); -} - -bool MemoryRegion::operator<(const MemoryRegion& rhs) const -{ - return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size < rhs.m_size)); -} - -bool MemoryRegion::operator>(const MemoryRegion& rhs) const -{ - return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size > rhs.m_size)); -} - -bool MemoryRegion::operator<=(const MemoryRegion& rhs) const -{ - return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size <= rhs.m_size)); -} - -bool MemoryRegion::operator>=(const MemoryRegion& rhs) const -{ - return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size >= rhs.m_size)); -} - -physaddr_t MemoryRegion::getLocation() const -{ - return m_location; -} - -size_t MemoryRegion::getSize() const -{ - return m_size; -} - -unsigned int MemoryRegion::getType() const -{ - return m_type; -} - -physaddr_t MemoryRegion::getEnd() const -{ - return m_location + m_size; -} - -bool MemoryRegion::contains(const MemoryRegion& r) const -{ - return contains(r.m_location, r.m_size); -} - -bool MemoryRegion::contains(physaddr_t location, size_t size) const -{ - return (location >= m_location) && - (location + size <= m_location + m_size); -} - -bool MemoryRegion::overlaps(const MemoryRegion& r) const -{ - if(r.m_location < m_location) - return r.m_location + r.m_size > m_location; - else - return r.m_location < getEnd(); -} - -bool MemoryRegion::bordersLeft(const MemoryRegion& right) const -{ - return getEnd() == right.m_location; -} - -bool MemoryRegion::bordersRight(const MemoryRegion& left) const -{ - return m_location == left.m_location + left.m_size; -} - -bool MemoryRegion::borders(const MemoryRegion& r) const -{ - return bordersLeft(r) || bordersRight(r); -} - -void MemoryRegion::truncateLeft(physaddr_t left) -{ - m_size = getEnd() - left; - m_location = left; -} - -void MemoryRegion::truncateRight(physaddr_t right) -{ - if(right > m_location) - m_size = right - m_location; - else - m_size = 0; -} \ No newline at end of file diff --git a/src/memoryregion.hpp b/src/memoryregion.hpp deleted file mode 100644 index 35e57e8..0000000 --- a/src/memoryregion.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef MEMORYBLOCK_H -#define MEMORYBLOCK_H - -#include "systypes.hpp" - -class MemoryRegion -{ -public: - - MemoryRegion(); - - MemoryRegion(const MemoryRegion& copy); - - MemoryRegion(physaddr_t location, size_t size, unsigned int type); - - const MemoryRegion& operator=(const MemoryRegion& rhs); - - /** - * @brief Tests whether this object describes the same region of memory - * as rhs, irrespective of type. - * - * @param rhs The object to compare to - * @return true if and only if the location and size of the two regions are equal - * @return false if the two regions have differing locations or differing sizes - */ - bool operator==(const MemoryRegion& rhs) const; - - /** - * @brief Tests whether this object describes a different region of memory - * than rhs, irrespective of type. - * - * @param rhs The object to compare to - * @return true if the two regions have differing locations or differing sizes - * @return false if and only if the location and size of the two regions are equal - */ - bool operator!=(const MemoryRegion& rhs) const; - - /** - * @brief - * - * @param rhs - * @return true - * @return false - */ - bool operator<(const MemoryRegion& rhs) const; - - bool operator>(const MemoryRegion& rhs) const; - - bool operator<=(const MemoryRegion& rhs) const; - - bool operator>=(const MemoryRegion& rhs) const; - - physaddr_t getLocation() const; - - size_t getSize() const; - - unsigned int getType() const; - - physaddr_t getEnd() const; - - bool contains(const MemoryRegion& r) const; - - bool contains(physaddr_t location, size_t size) const; - - bool overlaps(const MemoryRegion& r) const; - - bool bordersLeft(const MemoryRegion& right) const; - - bool bordersRight(const MemoryRegion& left) const; - - bool borders(const MemoryRegion& r) const; - - void truncateLeft(physaddr_t left); - - void truncateRight(physaddr_t right); - -private: - - physaddr_t m_location; - - size_t m_size; - - unsigned int m_type; - -}; - -#endif \ No newline at end of file diff --git a/src/memorytype.hpp b/src/memorytype.hpp deleted file mode 100644 index 99ea80b..0000000 --- a/src/memorytype.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef MEMORYTYPE_H -#define MEMORYTYPE_H - -enum class MemoryType -{ - Available = 1, - Unavailable = 2, - Defective = 3 -}; - -#endif \ No newline at end of file diff --git a/src/message.cpp b/src/message.cpp deleted file mode 100644 index 2f503d5..0000000 --- a/src/message.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "message.hpp" - -Message::Message() -{ - m_sender = 0; - m_type = 0; - m_args[0] = 0; - m_args[1] = 0; - m_args[2] = 0; -} - -Message::Message(const Message& copy) -{ - m_sender = copy.m_sender; - m_type = copy.m_type; - m_args[0] = copy.m_args[0]; - m_args[1] = copy.m_args[1]; - m_args[2] = copy.m_args[2]; -} - -Message::Message(unsigned int sender, unsigned int type, - unsigned long arg1, unsigned long arg2, unsigned long arg3) -{ - m_sender = sender; - m_type = type; - m_args[0] = arg1; - m_args[1] = arg2; - m_args[2] = arg3; -} - -Message& Message::operator=(const Message& rhs) -{ - m_sender = rhs.m_sender; - m_type = rhs.m_type; - m_args[0] = rhs.m_args[0]; - m_args[1] = rhs.m_args[1]; - m_args[2] = rhs.m_args[2]; -} \ No newline at end of file diff --git a/src/message.hpp b/src/message.hpp deleted file mode 100644 index 0702b1e..0000000 --- a/src/message.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef MESSAGE_H -#define MESSAGE_H - -struct Message -{ - - /** - * @brief Default constructor. Initializes all members to 0. - * - */ - Message(); - - /** - * @brief Copy constructor. - * - * @param copy - */ - Message(const Message& copy); - - /** - * @brief Construct a new Message object. - * - * @param sender - * @param type - * @param arg1 - * @param arg2 - * @param arg3 - */ - Message(unsigned int sender, unsigned int type, - unsigned long arg1, unsigned long arg2, unsigned long arg3); - - /** - * @brief Copy the contents of `rhs` to this object. - * - * @param rhs - * @return Message& - */ - Message& operator=(const Message& rhs); - - /** - * @brief PID of the process that generated this message. - */ - unsigned int m_sender; - - /** - * @brief Context-specific parameter which indicates to the receiver how - * the arguments are to be interpreted. - */ - unsigned int m_type; - - /** - * @brief Arguments of this message. The meaning of these values depend on - * context, as well as the values of `m_sender` and `m_type`. - */ - unsigned long m_args[3]; - -}; - -#endif \ No newline at end of file diff --git a/src/mmap.hpp b/src/mmap.hpp deleted file mode 100644 index 0e91955..0000000 --- a/src/mmap.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef MMAP_H -#define MMAP_H - -#include "pageallocator.hpp" - -#define MMAP_RW 0x01 -#define MMAP_EXEC 0x02 -#define MMAP_SHARED 0x04 - -namespace kernelns -{ - -int mmap(void* start, size_t length, int flags); - -int mmap(void* start, physaddr_t p_start, size_t length, int flags); - -int mapPage(void* start, physaddr_t p_start, int flags); - -int munmap(void* start, size_t length); - -bool isMapped(void* addr); - -physaddr_t getPhysicalAddress(void* addr); - -int createAddressSpace(void* table); - -int loadAddressSpace(physaddr_t table); - -} - -#endif \ No newline at end of file diff --git a/src/module.cpp b/src/module.cpp deleted file mode 100644 index 08ae855..0000000 --- a/src/module.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "module.hpp" -#include "util.hpp" - -using namespace kernelns; - -Module::Module() -{ - m_start = 0; - m_end = 0; - m_command = NULL; -} - -Module::Module(physaddr_t start, physaddr_t end, const char* command) -{ - m_start = start; - m_end = end; - m_command = new char[strlen(command) + 1]; - strcpy(m_command, command); -} - -Module::~Module() -{ - delete[] m_command; -} - -physaddr_t Module::getStart() const -{ - return m_start; -} - -physaddr_t Module::getEnd() const -{ - return m_end; -} - -const char* Module::getCommand() const -{ - return m_command; -} \ No newline at end of file diff --git a/src/module.hpp b/src/module.hpp deleted file mode 100644 index 2d3b024..0000000 --- a/src/module.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef ELF_H -#define ELF_H - -#include - -#include "systypes.hpp" - -namespace kernelns -{ - -class Module -{ -public: - - Module(); - - Module(physaddr_t start, physaddr_t end, const char* command); - - ~Module(); - - physaddr_t getStart() const; - - physaddr_t getEnd() const; - - const char* getCommand() const; - -private: - - physaddr_t m_start; - - physaddr_t m_end; - - char* m_command; - -}; - -} - -#endif \ No newline at end of file diff --git a/src/pageallocator.c b/src/pageallocator.c new file mode 100644 index 0000000..6289809 --- /dev/null +++ b/src/pageallocator.c @@ -0,0 +1,52 @@ +#include "pageallocator.h" +#include "types/status.h" + +physaddr_t reserve_page(struct page_stack_t *stack) +{ + if(stack->stack_pointer < stack->base_pointer) + { + physaddr_t frame = *stack->stack_pointer; + *stack->stack_pointer = (physaddr_t) 0; + stack->stack_pointer++; + return frame; + } + return S_OUT_OF_MEMORY; +} + +int free_page(struct page_stack_t *stack, physaddr_t location) +{ + if(stack->stack_pointer > stack->limit_pointer) + { + stack->stack_pointer--; + *stack->stack_pointer = location; + return S_OK; + } + return S_OUT_OF_MEMORY; +} + +size_t free_page_count(struct page_stack_t *stack) +{ + return stack->base_pointer - stack->stack_pointer; +} + +int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size) +{ + stack->total_pages = 0; + for(int i = 0; i < map->size; i++) + { + if(map->array[i].type != M_AVAILABLE) + { + continue; + } + size_t location = (map->array[i].location + page_size - 1) & ~(page_size - 1); + while(location + page_size <= map->array[i].location + map->array[i].size) + { + if(free_page(stack, location) != S_OK) + { + return S_OUT_OF_MEMORY; + } + stack->total_pages++; + location += page_size; + } + } +} diff --git a/src/pageallocator.hpp b/src/pageallocator.hpp deleted file mode 100755 index 2e600a7..0000000 --- a/src/pageallocator.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef __MEMORYALLOCATOR_H_ -#define __MEMORYALLOCATOR_H_ - -#include -#include "systypes.hpp" - -namespace kernelns -{ - -/** - * Interface for a physical memory allocator. - */ -class PageAllocator -{ -public: - - /** - * Allocate a single page, returning its physical address. Upon failure, - * returns an error code such that the least signifigant byte is nonzero. - */ - virtual physaddr_t next() = 0; - - /** - * Frees a single page that has previously been allocated. - */ - virtual void free(physaddr_t location) = 0; - - /** - * @returns the total number of free blocks of memory. - */ - virtual size_t freeBlocks() const = 0; - - /** - * @returns the total number of blocks managed by this memory - * allocator. - */ - virtual size_t getMemorySize() const = 0; - -}; - -} - -#endif diff --git a/src/pageallocatorstack.cpp b/src/pageallocatorstack.cpp deleted file mode 100644 index 8425dcd..0000000 --- a/src/pageallocatorstack.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "pageallocatorstack.hpp" -#include "memorytype.hpp" - -using namespace kernelns; - -PageAllocatorStack::PageAllocatorStack(physaddr_t *stackBase, physaddr_t *stackTop, size_t frameSize, const MemoryMap& memoryMap) -{ - m_base = stackBase; - m_top = stackTop; - m_stack = m_base; - for(int i = 0; i < memoryMap.size(); i++) - { - if((MemoryType) memoryMap[i].getType() == MemoryType::Available) - { - for(int j = 0; j < memoryMap[i].getSize() / frameSize; j++) - { - free(memoryMap[i].getLocation() + j * frameSize); - } - } - } -} - -physaddr_t PageAllocatorStack::next() -{ - if(m_stack < m_base) - { - physaddr_t frame = *m_stack; - *m_stack = (physaddr_t) 0; - m_stack++; - return frame; - } - return (physaddr_t) -1; -} - -void PageAllocatorStack::free(physaddr_t location) -{ - if(m_stack > m_top) - { - m_stack--; - *m_stack = location; - } -} - -size_t PageAllocatorStack::freeBlocks() const -{ - return m_base - m_stack; -} - -size_t PageAllocatorStack::getMemorySize() const -{ - return m_totalSize; -} \ No newline at end of file diff --git a/src/pageallocatorstack.hpp b/src/pageallocatorstack.hpp deleted file mode 100644 index f5710ed..0000000 --- a/src/pageallocatorstack.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef PAGEALLOCATORSTACK_H -#define PAGEALLOCATORSTACK_H - -#include "pageallocator.hpp" -#include "memorymap.hpp" - -namespace kernelns -{ - -class PageAllocatorStack : public PageAllocator -{ -public: - - PageAllocatorStack(physaddr_t *stackBase, physaddr_t *stackTop, size_t frameSize, const MemoryMap& memoryMap); - - virtual physaddr_t next(); - - virtual void free(physaddr_t location); - - virtual size_t freeBlocks() const; - - virtual size_t getMemorySize() const; - -private: - - size_t m_totalSize; - - physaddr_t *m_stack, *m_base, *m_top; - -}; - -} - -#endif \ No newline at end of file diff --git a/src/priorityqueue.c b/src/priorityqueue.c new file mode 100644 index 0000000..5ab2873 --- /dev/null +++ b/src/priorityqueue.c @@ -0,0 +1,67 @@ +#include "priorityqueue.h" +#include "types/status.h" + +void heapify(struct priority_queue_t *queue, size_t i) +{ + if(i * 2 + 1 >= queue->size) + { + return; + } + else if(queue->heap[i * 2 + 1]->priority <= queue->heap[i]->priority + && queue->heap[i * 2 + 1]->priority <= queue->heap[i * 2 + 2]->priority) + { + struct process_t *buffer = queue->heap[i]; + queue->heap[i] = queue->heap[i * 2 + 1]; + queue->heap[i * 2 + 1] = buffer; + heapify(queue, i * 2 + 1); + } + else if(queue->heap[i * 2 + 2]->priority <= queue->heap[i]->priority + && queue->heap[i * 2 + 2]->priority <= queue->heap[i * 2 + 1]->priority) + { + struct process_t *buffer = queue->heap[i]; + queue->heap[i] = queue->heap[i * 2 + 2]; + queue->heap[i * 2 + 2] = buffer; + heapify(queue, i * 2 + 2); + } +} + +struct process_t *extract_min(struct priority_queue_t *queue) +{ + if(queue->size == 0) + return NULL; + queue->size--; + struct process_t *p = queue->heap[0]; + queue->heap[0] = queue->heap[queue->size]; + heapify(queue, 0); + return p; +} + +int insert(struct priority_queue_t *queue, struct process_t *process) +{ + if(queue->size == queue->capacity) + return S_OUT_OF_MEMORY; + size_t i = queue->size; + queue->size++; + while(i > 0 && queue->heap[(i - 1) / 2]->priority > process->priority) + { + queue->heap[i] = queue->heap[(i - 1) / 2]; + i = (i - 1) / 2; + } + queue->heap[i] = process; + return S_OK; +} + +int remove(struct priority_queue_t *queue, struct process_t *process) +{ + for(size_t i = 0; i < queue->size; i++) + { + if(queue->heap[i] == process) + { + queue->size--; + queue->heap[i] = queue->heap[queue->size]; + heapify(queue, i); + return S_OK; + } + } + return S_OUT_OF_BOUNDS; +} \ No newline at end of file diff --git a/src/process.hpp b/src/process.hpp deleted file mode 100644 index b25238f..0000000 --- a/src/process.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef PROCESS_H -#define PROCESS_H - -#include - -#include "message.hpp" - -namespace kernelns -{ - -class Process -{ -public: - - size_t priority; - - void* stack; - - Process(); - - unsigned int getID() const; - - bool map(void* location, size_t size); - - /** - * @brief If the specified region is mapped and does not overlap a shared - * or private block, or the kernel, removes that region from the process's - * internal memory map. If the specified region overlaps an unmapped region, - * a shared or private block, or the kernel, the object goes unmodified. - * This method does not affect the page tables in any way, only the process's - * internal bookkeeping. - * - * @param location - * @param size - * @return true if the memory map was sucessfully updated - * @return false if the memory map was not modified - */ - bool unmap(void* location, size_t size); - - bool hasSharedBlock(unsigned int blockID) const; - - bool hasPhysicalBlock(unsigned int blockID) const; - - void pushMessage(Message* message); - - Message* popMessage(); - -private: - -}; - -} - -#endif \ No newline at end of file diff --git a/src/sharedblock.hpp b/src/sharedblock.hpp deleted file mode 100644 index e9fe3d6..0000000 --- a/src/sharedblock.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SHAREDBLOCK_H -#define SHAREDBLOCK_H - -#include "memoryregion.hpp" - -class SharedBlock : public MemoryRegion -{ -public: - - unsigned int getFlags() const; - -private: - - unsigned int m_flags; - -}; - -#endif \ No newline at end of file diff --git a/src/stdio.c b/src/stdio.c new file mode 100644 index 0000000..1e2165d --- /dev/null +++ b/src/stdio.c @@ -0,0 +1,100 @@ +#include "stdio.h" +#include +#include + +enum format_flags_t +{ + FORMAT_PADDING = '0', + FORMAT_WIDTH = '*', + + FORMAT_SIGNED_DECIMAL = 'i', + FORMAT_UNSIGNED_DECIMAL = 'u', + FORMAT_UNSIGNED_OCTAL = 'o', + FORMAT_UNSIGNED_HEX = 'x', + FORMAT_STRING = 's', + FORMAT_COUNT = 'n', + FORMAT_PERCENT = '%' + +}; + +char *itoa(unsigned int n, unsigned int base, unsigned int width) +{ + if (base < 2 || base > 16) + { + return NULL; + } + static const char *digits = "0123456789abcdef"; + static char buffer[65]; + char *s = &buffer[64]; + unsigned int count = 0; + do + { + *--s = digits[n % base]; + n /= base; + count++; + } while (count < width || n != 0); + return s; +} + +int printf(const char *format, ...) +{ + va_list valist; + va_start(valist, format); + while (*format) + { + if (*format == '%') + { + size_t width = 0; + bool padding = false; + switch (*++format) + { + case FORMAT_PADDING: + padding = true; + format++; + break; + } + while (*format >= '0' && *format <= '9') + { + width = (width * 10) + *format - '0'; + format++; + } + switch (*format) + { + case FORMAT_SIGNED_DECIMAL:; + int n = va_arg(valist, int); + if (n < 0) + { + putchar('-'); + n *= -1; + } + puts(itoa((unsigned int)n, 10, width)); + break; + case FORMAT_UNSIGNED_DECIMAL: + puts(itoa(va_arg(valist, unsigned int), 10, width)); + break; + case FORMAT_UNSIGNED_OCTAL: + puts(itoa(va_arg(valist, unsigned int), 8, width)); + case FORMAT_UNSIGNED_HEX: + puts(itoa(va_arg(valist, unsigned int), 16, width)); + break; + case FORMAT_STRING: + puts(va_arg(valist, const char *)); + break; + case FORMAT_PERCENT: + putchar('%'); + break; + } + } + else + { + putchar(*format); + } + format++; + } + va_end(valist); + return 0; +} + +int sprintf(char *str, const char *format, ...) +{ +} \ No newline at end of file diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..4dd71ab --- /dev/null +++ b/src/string.c @@ -0,0 +1,110 @@ +#include "string.h" +#include +#include + +void *memcpy(void *destination, const void *source, size_t num) +{ + if (num > 0) + { + const uint8_t *src = (const uint8_t *)source; + uint8_t *dest = (uint8_t *)destination; + for (size_t i = 0; i < num; i++) + { + dest[i] = src[i]; + } + } + return destination; +} + +void *memmove(void *destination, const void *source, size_t num) +{ + if (num > 0) + { + if (((size_t)destination) < ((size_t)source) || ((size_t)destination) >= (((size_t)source)) + num) + { + return memcpy(destination, source, num); + } + else if (destination != source) + { + size_t i = num - 1; + const uint8_t *src = (const uint8_t *)source; + uint8_t *dest = (uint8_t *)destination; + do + { + dest[i] = src[i]; + i--; + } while (i != 0); + } + } + return destination; +} + +int memcmp(const void *ptr1, const void *ptr2, size_t num) +{ + const uint8_t *a = (const uint8_t *)ptr1; + const uint8_t *b = (const uint8_t *)ptr2; + for (size_t i = 0; i < num; i++) + { + if (a[i] < b[i]) + return -1; + else if (a[i] > b[i]) + return 1; + } + return 0; +} + +void *memset(void *ptr, int value, size_t num) +{ + uint8_t *dest = (uint8_t *)ptr; + uint8_t v = (uint8_t)value; + for (size_t i = 0; i < num; i++) + { + dest[i] = v; + } + return ptr; +} + +int strlen(const char *str) +{ + int i = 0; + while (str[i] != '\0') + { + i++; + } + return i; +} + +char *strcpy(char *destination, const char *source) +{ + int sourceLen = strlen(source); + if ((destination <= source) || (destination > (source + sourceLen))) + { + char *d = destination; + const char *s = source; + while (true) + { + *d = *s; + if (*s == '\0') + { + break; + } + else + { + s++; + d++; + } + } + } + else + { + char *d = destination + sourceLen; + const char *s = source + sourceLen; + do + { + *d = *s; + d--; + s--; + } while (d > destination); + } + return destination; +} diff --git a/src/syscalls.cpp b/src/syscalls.cpp deleted file mode 100644 index 30e3918..0000000 --- a/src/syscalls.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "syscalls.hpp" -#include "kernel.hpp" -#include "memorytype.hpp" - -int mmap(void* location, size_t length, int flags) -{ - if(kernel.getActiveProcess().map(location, length)) - { - if(kernel.allocateRegion(location, length, flags)) - return 0; - else if(kernel.getActiveProcess().unmap(location, length)) - return 1; - kernel.terminateActiveProcess(); - } - return kernel.allocateRegion(location, length, flags); -} - -int munmap(void* location, size_t length) -{ - if(kernel.getActiveProcess().unmap(location, length)) - { - kernel.freeRegion(location, length); - return 0; - } - return 1; -} - -unsigned int createSharedBlock(void* location, size_t length, int flags) -{ - unsigned int blockID = kernel.createSharedBlock(length, flags); - if(blockID > 0) - { - const SharedBlock& block = kernel.getSharedBlock(blockID); - kernel.mapRegion(location, block.getLocation(), length, flags); - // TODO: add block to current process - // TODO: perform safety checks - } - return blockID; -} - -int aquireSharedBlock(void* location, unsigned int id) -{ - const SharedBlock& block = kernel.getSharedBlock(id); - kernel.mapRegion(location, block.getLocation(), block.getSize(), block.getFlags()); - // TODO: (somehow) handle invalid ids -- possibly hard while using references - // TODO: add block to current process - // TODO: perform safety checks - return 0; -} - -int releaseSharedBlock(int id) -{ - // (0) Check that process actually posesses block - // (1) Get virtual address of block - // (2) Unmap block - // (3) Delete block if no one posesses it anymore - return 0; -} - -int querySharedBlock(void* info, int id) -{ - // TODO: define struct for block info -} - -int aquirePhysicalBlock(void* location, physaddr_t physicalAddress, size_t length) -{ - return 0; -} - -int releasePhysicalBlock(int id) -{ - return 0; -} - -int sendMessage(unsigned int recipient, const Message* message) -{ - Message* copy = new Message(*message); - copy->m_sender = kernel.getActiveProcess().getID(); - kernel.getProcess(recipient).pushMessage(copy); - return 0; -} - -int receiveMessage(Message* buffer) -{ - if(buffer == nullptr) - return 1; - Message* message = kernel.getActiveProcess().popMessage(); - if(message == nullptr) - return 1; - *buffer = *message; - delete message; - return 0; -} \ No newline at end of file diff --git a/src/syscalls.hpp b/src/syscalls.hpp deleted file mode 100644 index 5364426..0000000 --- a/src/syscalls.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include "systypes.hpp" -#include "message.hpp" - -int mmap(void* location, size_t length, int flags); - -int munmap(void* location, size_t length); - -unsigned int createSharedBlock(void* location, size_t length, int flags); - -int aquireSharedBlock(void* location, unsigned int id); - -int releaseSharedBlock(int id); - -int querySharedBlock(void* info, int id); - -int aquirePhysicalBlock(void* location, physaddr_t physicalAddress, size_t length); - -int releasePhysicalBlock(int id); - -int sendMessage(unsigned int recipient, const Message* message); - -int receiveMessage(Message* buffer); - -#endif \ No newline at end of file diff --git a/src/systypes.hpp b/src/systypes.hpp deleted file mode 100644 index 2487de5..0000000 --- a/src/systypes.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef SYSTYPES_H -#define SYSTYPES_H - -#include "types/physaddr.h" -#include "types/status.h" -#include "types/handle.h" - -#endif diff --git a/src/types/handle.h b/src/types/handle.h deleted file mode 100644 index 6444d60..0000000 --- a/src/types/handle.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef HANDLE_H -#define HANDLE_H - -#include - -typedef uint64_t handle_t; - -#endif \ No newline at end of file diff --git a/src/types/status.h b/src/types/status.h deleted file mode 100644 index 3771191..0000000 --- a/src/types/status.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef STATUS_H -#define STATUS_H - -enum class Status -{ - OK = 0, - BadArgument, - NoMemory -}; - -#endif \ No newline at end of file diff --git a/src/util.cpp b/src/util.cpp deleted file mode 100644 index 1256dbc..0000000 --- a/src/util.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#include - -#include "util.hpp" -#include "kernel.hpp" - -void* memcpy(void* destination, const void* source, size_t num) -{ - if(num > 0) - { - const uint8_t* src = (const uint8_t*) source; - uint8_t* dest = (uint8_t*) destination; - for(size_t i = 0; i < num; i++) - { - dest[i] = src[i]; - } - } - return destination; -} - -void* memmove(void* destination, const void* source, size_t num) -{ - if(num > 0) - { - if(((size_t) destination) < ((size_t) source) || ((size_t) destination) >= (((size_t) source)) + num) - { - return memcpy(destination, source, num); - } - else if(destination != source) - { - size_t i = num - 1; - const uint8_t* src = (const uint8_t*) source; - uint8_t* dest = (uint8_t*) destination; - do - { - dest[i] = src[i]; - i--; - } while(i != 0); - } - } - return destination; -} - -int memcmp(const void* ptr1, const void* ptr2, size_t num) -{ - const uint8_t* a = (const uint8_t*) ptr1; - const uint8_t* b = (const uint8_t*) ptr2; - for(size_t i = 0; i < num; i++) - { - if(a[i] < b[i]) - return -1; - else if(a[i] > b[i]) - return 1; - } - return 0; -} - -void* memset(void* ptr, int value, size_t num) -{ - uint8_t* dest = (uint8_t*) ptr; - uint8_t v = (uint8_t) value; - for(size_t i = 0; i < num; i++) - { - dest[i] = v; - } - return ptr; -} - -int strlen(const char* str) -{ - int i = 0; - while(str[i] != '\0') - { - i++; - } - return i; -} - -char* strcpy(char* destination, const char* source) -{ - int sourceLen = strlen(source); - if((destination <= source) || (destination > (source + sourceLen))) - { - char* d = destination; - const char* s = source; - while(true) - { - *d = *s; - if(*s == '\0') - { - break; - } - else - { - s++; - d++; - } - } - } - else - { - char* d = destination + sourceLen; - const char* s = source + sourceLen; - do - { - *d = *s; - d--; - s--; - } while(d > destination); - } - return destination; -} - -void* malloc(size_t size) -{ - return kernel.malloc(size); -} - -void* calloc(size_t count, size_t size) -{ - void* ptr = malloc(count * size); - if(ptr != nullptr) - memset(malloc(count * size), 0, count * size); - return ptr; -} - -void* realloc(void* ptr, size_t size) -{ - void* n = kernel.malloc(size); - if(n != nullptr) - { - memmove(n, ptr, size); - free(ptr); - } - return n; -} - -void free(void* p) -{ - kernel.free(p); -} - -void __cxa_pure_virtual() -{ - // do nothing -} - -void* operator new(size_t size) -{ - return malloc(size); -} - -void* operator new[](size_t size) -{ - return malloc(size); -} - -void operator delete(void* p) -{ - free(p); -} - -void operator delete[](void* p) -{ - free(p); -} \ No newline at end of file diff --git a/src/util.hpp b/src/util.hpp deleted file mode 100644 index d82bcf5..0000000 --- a/src/util.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef UTIL_H -#define UTIL_H - -#include - -extern "C" void* memcpy(void* destination, const void* source, size_t num); - -extern "C" void* memmove(void* destination, const void* source, size_t num); - -extern "C" int memcmp(const void* ptr1, const void* ptr2, size_t num); - -extern "C" void* memset(void* ptr, int value, size_t num); - -extern "C" int strlen(const char* str); - -extern "C" char* strcpy(char* destination, const char* source); - -extern "C" void* malloc(size_t size); - -extern "C" void* calloc(size_t count, size_t size); - -extern "C" void* realloc(void* ptr, size_t size); - -extern "C" void free(void* p); - -extern "C" void __cxa_pure_virtual(); - -void* operator new(size_t size); - -void* operator new[](size_t size); - -void operator delete(void* p); - -void operator delete[](void* p); - -inline void* operator new(size_t, void *p) -{ - return p; -} - -inline void* operator new[](size_t, void *p) -{ - return p; -} - -inline void operator delete(void *, void *) -{ - -} - -inline void operator delete[](void *, void *) -{ - -} - -#endif \ No newline at end of file diff --git a/src/x86/apic.c b/src/x86/apic.c new file mode 100644 index 0000000..9d6d113 --- /dev/null +++ b/src/x86/apic.c @@ -0,0 +1,35 @@ +#include "apic.h" + +void apic_enable() +{ + +} + +void apic_eoi() +{ + apic_registers->eoi.value = 0; +} + +void apic_send_ipi( + uint32_t vector, + enum apic_delivery_mode_t delivery_mode, + enum apic_destination_mode_t destination_mode, + enum apic_level_t level, + enum apic_trigger_mode_t trigger_mode, + enum apic_destination_shorthand_t shorthand, + uint32_t destination) +{ + struct apic_icr_t value = { + .vector = vector, + .delivery_mode = delivery_mode, + .destination_mode = destination_mode, + .level = level, + .trigger_mode = trigger_mode, + .destination_shorthand = shorthand, + .destination = destination + }; + uint32_t *value_addr = (uint32_t*) &value; + uint32_t *icr_addr = (uint32_t*)&apic_registers->interrput_command; + icr_addr[4] = value_addr[4]; + icr_addr[0] = value_addr[0]; +} \ No newline at end of file diff --git a/src/x86/apic.h b/src/x86/apic.h new file mode 100644 index 0000000..65e7739 --- /dev/null +++ b/src/x86/apic.h @@ -0,0 +1,156 @@ +#pragma once + +#include + +enum apic_delivery_mode_t +{ + APIC_DELIVERY_MODE_FIXED = 0b000, + APIC_DELIVERY_MODE_LOWEST_PRIORITY = 0b001, + APIC_DELIVERY_MODE_SMI = 0b010, + APIC_DELIVERY_MODE_NMI = 0b100, + APIC_DELIVERY_MODE_INIT = 0b101, + APIC_DELIVERY_MODE_SIPI = 0b110, + APIV_DELIVERY_MODE_EXTINIT = 0b111 +}; + +enum apic_destination_mode_t +{ + APIC_DESTINATION_MODE_PHYSICAL = 0, + APIC_DESTINATION_MODE_LOGICAL = 1 +}; + +enum apic_level_t +{ + APIC_LEVEL_DEASSERT = 0, + APIC_LEVEL_ASSERT = 1 +}; +enum apic_trigger_mode_t +{ + APIC_TRIGGER_MODE_EDGE = 0, + APIC_TRIGGER_MODE_LEVEL = 1 +}; + +enum apic_destination_shorthand_t +{ + APIC_DEST_SHORTHAND_NONE = 0, + APIC_DEST_SHORTHAND_SELF = 1, + APIC_DEST_SHORTHAND_ALL = 2, + APIC_DEST_SHORTHAND_OTHERS = 3 +}; + +enum apic_divide_mode_t +{ + APIC_DIVIDE_1 = 0b1011, + APIC_DIVIDE_2 = 0b0000, + APIC_DIVIDE_4 = 0b0001, + APIC_DIVIDE_8 = 0b0010, + APIC_DIVIDE_16 = 0b0011, + APIC_DIVIDE_32 = 0b1000, + APIC_DIVIDE_64 = 0b1001, + APIC_DIVIDE_128 = 0b1011 +}; + +enum apic_timer_mode_t +{ + APIC_TIMER_ONESHOT = 0, + APIC_TIMER_PERIODIC = 1, + APIC_TIMER_TSCDEADLINE = 2 +}; + +struct apic_register_t +{ + uint32_t value; + uint32_t padding[3]; +}; + +struct apic_lapic_version_t +{ + uint32_t version : 8; + uint32_t reserved_1 : 8; + uint32_t max_lvt_entry : 8; + uint32_t suppress_eoi_broadcast : 1; + uint32_t reserved_2 : 7; + uint32_t padding[3]; +}; + +struct apic_lvt_t +{ + uint32_t vector: 8; + uint32_t delivery_mode : 3; + uint32_t reserved_1 : 1; + uint32_t delivery_status : 1; + uint32_t pin_polarity : 1; + uint32_t remote_irr : 1; + uint32_t trigger_mode : 1; + uint32_t mask : 1; + uint32_t timer_mode : 2; + uint32_t reserved_2 : 13; + uint32_t padding[3]; +}; + +struct apic_icr_t +{ + uint32_t vector : 8; + uint32_t delivery_mode : 3; + uint32_t destination_mode : 1; + uint32_t delivery_status : 1; + uint32_t reserved_1 : 1; + uint32_t level : 1; + uint32_t trigger_mode : 1; + uint32_t reserved_2 : 2; + uint32_t destination_shorthand : 2; + uint32_t reserved_3 : 12; + uint32_t padding_1[3]; + uint32_t reserved : 24; + uint32_t destination : 8; + uint32_t padding_2[3]; +}; + +struct apic_registers_t +{ + struct apic_register_t reserved_1[2]; + struct apic_register_t lapic_id; + struct apic_lapic_version_t lapic_version; + struct apic_register_t reserved_2[4]; + struct apic_register_t task_priority; + struct apic_register_t arbitration_priority; + struct apic_register_t processor_priority; + struct apic_register_t eoi; + struct apic_register_t remote_read; + struct apic_register_t logical_destination; + struct apic_register_t destination_format; + struct apic_register_t spurious_iv; + struct apic_register_t in_service[8]; + struct apic_register_t trigger_mode[8]; + struct apic_register_t interrupt_request[8]; + struct apic_register_t error_status; + struct apic_register_t reserved_3[6]; + struct apic_lvt_t lvt_cmci; + struct apic_icr_t interrput_command; + struct apic_lvt_t lvt_timer; + struct apic_lvt_t lvt_thermal_sensor; + struct apic_lvt_t lvt_performance_counters; + struct apic_lvt_t lvt_lint0; + struct apic_lvt_t lvt_lint1; + struct apic_lvt_t lvt_error; + struct apic_register_t initial_count; + struct apic_register_t current_count; + struct apic_register_t reserved_4[4]; + struct apic_register_t divide_config; + struct apic_register_t reserved_5; +}; + +extern struct apic_registers_t volatile *apic_registers; + +void apic_enable(); + +void apic_eoi(); + +void apic_send_ipi( + uint32_t vector, + enum apic_delivery_mode_t delivery_mode, + enum apic_destination_mode_t destination_mode, + enum apic_level_t level, + enum apic_trigger_mode_t trigger_mode, + enum apic_destination_shorthand_t shorthand, + uint32_t destination); diff --git a/src/x86/entry.S b/src/x86/entry.S index fd6c079..6ec1c8b 100755 --- a/src/x86/entry.S +++ b/src/x86/entry.S @@ -124,7 +124,7 @@ _tempPgDir: _tempIdentityMap: .skip 4096 _tempPgTable: -.skip 8192 +.skip 4096 _bootCmdLine: .skip 64 @@ -143,6 +143,9 @@ memory_map: .global _start .type _start, @function _start: + + cli + # This platform reqires a Multiboot2 bootloader. cmp $0x36d76289, %eax jne .err @@ -212,12 +215,6 @@ _start: push %ebx call initialize - # mov $_bootCmdLine, %eax - # push %eax - - # Call main function - # call main - .err: cli 2: hlt diff --git a/src/x86/initialize.cpp b/src/x86/initialize.cpp deleted file mode 100644 index 361cd4f..0000000 --- a/src/x86/initialize.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include "multiboot2.hpp" -#include "tty.hpp" -#include "../mmap.hpp" -#include "../util.hpp" -#include "../memorytype.hpp" - -using namespace kernelns; - -extern int _kernelEnd; - -extern "C" -int startPaging(uint32_t* directory, uint32_t* table, uint32_t* identityTable) -{ - for(int i = 0; i < 1024; i++) - { - uint32_t pte = i * 4096 + 3; - table[i] = pte; - identityTable[i] = pte; - } - directory[0] = ((uint32_t) identityTable) + 3; - directory[1022] = ((uint32_t) table) + 3; - directory[1023] = ((uint32_t) directory) + 3; - asm("mov %0, %%cr3" - : - : "r" (directory)); - asm("mov %%cr0, %%eax \n" - "or $0x80010000, %%eax \n" - "mov %%eax, %%cr0" - : - : - : "eax"); - return 0; -} - -extern "C" -int initialize(void* multibootInfo) -{ - size_t heapSize = 0xFFC00000 - (size_t) &_kernelEnd; - int log = 0; - for(; heapSize > 1; log++) - heapSize >>= 1; - heapSize <<= log; - //new(&State::allocator) Allocator((void*) (0xFFC00000 - heapSize), heapSize, 64); - Multiboot2Info bootInfo(multibootInfo); - if(!bootInfo.isValid()) - return 1; - bootInfo.getMemoryMap().insertEntry(0, 4 * 1024 * 1024, (unsigned int) MemoryType::Unavailable); - //new(&State::config) SystemInfo(bootInfo.getMemoryMap(), bootInfo.getCommandLine()); - TTY tty((char*) 0xFF8B8000); - tty << "Type\t\tLocation\t\tSize\n"; - for(size_t i = 0; i < bootInfo.getMemoryMap().size() && bootInfo.getMemoryMap()[i].getSize() > 0; i++) - { - tty << (int) bootInfo.getMemoryMap()[i].getType() << "\t\t\t"; - tty << (void*) bootInfo.getMemoryMap()[i].getLocation() << "\t\t"; - tty << (int) bootInfo.getMemoryMap()[i].getSize() << "\n"; - } - // TODO: Initialize page allocator - // TODO: Initialize process queue, add entry for each module - return 0; -} diff --git a/src/x86/interrupts.c b/src/x86/interrupts.c new file mode 100644 index 0000000..aadce4a --- /dev/null +++ b/src/x86/interrupts.c @@ -0,0 +1,29 @@ +#include "interrupts.h" + +struct idt_info_t +{ + uint16_t size; + void *location; +} __attribute__ ((packed)); + +void lidt(struct interrupt_descriptor_t *idt) +{ + struct idt_info_t idt_info; + idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1; + idt_info.location = (void *)idt; + asm("lidt (%0)" + : + : "r"(&idt_info)); +} + +void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage) +{ + descriptor->offset_1 = (uint32_t) isr & 0xFFFF; + descriptor->offset_2 = (uint32_t) isr >> 16; + descriptor->selector = 8; + descriptor->zero = 0; + descriptor->type = type; + descriptor->storage = 0; + descriptor->dpl = privilage; + descriptor->present = 1; +} diff --git a/src/x86/interrupts.cpp b/src/x86/interrupts.cpp deleted file mode 100644 index 6eda16d..0000000 --- a/src/x86/interrupts.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include "../interrupts.hpp" - -#include -#include - -class InterruptDescriptor -{ -public: - - enum Type - { - TASK32 = 5, - TRAP32 = 15, - INT32 = 14, - TRAP16 = 7, - INT16 = 6 - }; - - InterruptDescriptor() - { - this->m_offset1 = 0; - this->m_selector = 0; - this->m_zero = 0; - this->m_type = 0; - this->m_storage = 0; - this->m_dpl = 0; - this->m_present = 0; - this->m_offset2 = 0; - } - - InterruptDescriptor(void* handler, Type type, unsigned int dpl) - { - uint32_t offset = (uint32_t) handler; - this->m_offset1 = (uint16_t) offset; - this->m_selector = 8; - this->m_zero = 0; - this->m_type = (uint16_t) type; - this->m_storage = 0; - this->m_dpl = dpl; - this->m_present = 1; - this->m_offset2 = offset >> 16; - } - - bool present() - { - return m_present == 1; - } - - void present(bool present) - { - m_present = present ? 1 : 0; - } - - Type type() - { - return (Type) m_type; - } - - void type(Type type) - { - m_type = (unsigned int) type; - } - - unsigned int dpl() - { - return m_dpl; - } - - void dpl(unsigned int dpl) - { - m_dpl = dpl; - } - - void* operator=(void* rhs) - { - uint32_t offset = (uint32_t) rhs; - m_offset1 = (uint16_t) offset; - m_offset2 = (offset >> 16); - return rhs; - } - -private: - - uint16_t m_offset1; - uint16_t m_selector; - uint16_t m_zero : 8; - uint16_t m_type : 4; - uint16_t m_storage : 1; - uint16_t m_dpl : 2; - uint16_t m_present : 1; - uint16_t m_offset2; - -}; - -struct IDTInfo -{ - uint16_t size; - void* location; -}; - -InterruptDescriptor idt[256]; - -void lidt() -{ - IDTInfo idtInfo; - idtInfo.size = sizeof(idt) - 1; - idtInfo.location = (void*) &idt; - asm("lidt (%0)" - : - : "r" (&idtInfo)); -} - -__attribute__ ((interrupt)) -void divisionByZero(void* frame) -{ - -} - -__attribute__ ((interrupt)) -void gpFaultHandler(void* frame, unsigned int error) -{ - -} - -__attribute__ ((interrupt)) -void pageFaultHandler(void* frame, unsigned int error) -{ - -} - -__attribute__ ((interrupt)) -void doubleFaultHandler(void* frame, unsigned int error) -{ - asm("hlt"); -} - -__attribute__ ((interrupt)) -void syscallHandler(void* frame) -{ - -} - -kernelns::Interrupts::Interrupts() -{ - for(unsigned int i = 0; i <= MAX_SYSCALL_ID; i++) - syscalls[i] = (void*) NULL; - idt[0] = InterruptDescriptor((void*) &divisionByZero, InterruptDescriptor::INT32, 0); - idt[8] = InterruptDescriptor((void*) &doubleFaultHandler, InterruptDescriptor::INT32, 0); - idt[0x80] = InterruptDescriptor((void*) &syscallHandler, InterruptDescriptor::INT32, 0); - // Load interrupt handlers - // Configure PIC - lidt(); -} - -void kernelns::Interrupts::enable() -{ - asm("sti"); -} - -void kernelns::Interrupts::disable() -{ - asm("cli"); -} - -void kernelns::Interrupts::addSyscall(unsigned int id, void* function) -{ - if(id <= MAX_SYSCALL_ID) - syscalls[id] = function; -} \ No newline at end of file diff --git a/src/x86/interrupts.h b/src/x86/interrupts.h new file mode 100644 index 0000000..d8ff3b9 --- /dev/null +++ b/src/x86/interrupts.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +enum interrupt_code_t +{ + EXCEPTION_DIV_BY_0 = 0, + EXCEPTION_DEBUG = 1, + EXCEPTION_NMI = 2, + EXCEPTION_BREAKPOINT = 3, + EXCEPTION_OVERFLOW = 4, + EXCEPTION_OUT_OF_BOUNDS = 5, + EXCEPTION_INVALID_OPCODE = 6, + EXCEPTION_DEVICE_NOT_AVAILABLE = 7, + EXCEPTION_DOUBLE_FAULT = 8, + EXCEPTION_INVALID_TSS = 10, + EXCEPTION_SEGMENT_NOT_PRESENT = 11, + EXCEPTION_STACK_SEGMENT_FAULT = 12, + EXCEPTION_GPF = 13, + EXCEPTION_PAGE_FAULT = 14, + EXCEPTION_x87_FLOATING_POINT = 16, + EXCEPTION_ALIGNMENT_CHECK = 17, + EXCEPTION_MACHINE_CHECK = 18, + EXCEPTION_SIMD_FLOATING_POINT = 19, + EXCEPTION_VIRTUALIZATION = 20, + EXCEPTION_SECURITY = 30, + ISR_AP_START = 127, + ISR_SYSCALL = 128 +}; + +enum isr_type_t +{ + INTERRPUT_TASK32 = 5, + INTERRPUT_TRAP32 = 15, + INTERRPUT_INT32 = 14, + INTERRPUT_TRAP16 = 7, + INTERRPUT_INT16 = 6 +}; + +struct interrupt_descriptor_t +{ + uint16_t offset_1; + uint16_t selector; + uint16_t zero : 8; + uint16_t type : 4; + uint16_t storage : 1; + uint16_t dpl : 2; + uint16_t present : 1; + uint16_t offset_2; +}; + +void lidt(struct interrupt_descriptor_t *idt); + +void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage); diff --git a/src/x86/isr.c b/src/x86/isr.c new file mode 100644 index 0000000..8d36841 --- /dev/null +++ b/src/x86/isr.c @@ -0,0 +1,41 @@ +#include "isr.h" +#include "stdio.h" + +__attribute__ ((interrupt)) +void isr_division_by_zero(void* frame) +{ + printf("Exception: Division by zero\n"); +} + +__attribute__ ((interrupt)) +void isr_gp_fault(void* frame, unsigned int error) +{ + +} + +__attribute__ ((interrupt)) +void isr_page_fault(void* frame, unsigned int error) +{ + +} + +__attribute__ ((interrupt)) +void isr_double_fault(void* frame, unsigned int error) +{ + asm("hlt"); +} + +__attribute__ ((naked)) +void isr_ap_start(void* frame) +{ + asm(".code16"); + //... + asm(".code32"); + // do something useful +} + +__attribute__ ((interrupt)) +void isr_syscall(void* frame) +{ + +} \ No newline at end of file diff --git a/src/x86/isr.h b/src/x86/isr.h new file mode 100644 index 0000000..1725d53 --- /dev/null +++ b/src/x86/isr.h @@ -0,0 +1,19 @@ +#pragma once + +__attribute__ ((interrupt)) +void isr_division_by_zero(void* frame); + +__attribute__ ((interrupt)) +void isr_gp_fault(void* frame, unsigned int error); + +__attribute__ ((interrupt)) +void isr_page_fault(void* frame, unsigned int error); + +__attribute__ ((interrupt)) +void isr_double_fault(void* frame, unsigned int error); + +__attribute__ ((naked)) +void isr_ap_start(void* frame); + +__attribute__ ((interrupt)) +void isr_syscall(void* frame); \ No newline at end of file diff --git a/src/x86/linker.ld b/src/x86/linker.ld index df4267a..bf01f37 100755 --- a/src/x86/linker.ld +++ b/src/x86/linker.ld @@ -38,5 +38,5 @@ SECTIONS _heapLocation = 0xFFB00000; _heapSize = 0x100000; _kernelStart = VIRTUAL_BASE; - _kernelEnd = VIRTUAL_BASE + (4096 * IMAGE_SIZE); + _kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE); } diff --git a/src/x86/memorymanagerx86.cpp b/src/x86/memorymanagerx86.cpp deleted file mode 100644 index b4aaefc..0000000 --- a/src/x86/memorymanagerx86.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "memorymanagerx86.hpp" - -unsigned int MemoryManagerx86::getPageSize() const -{ - return pageSize; -} - -physaddr_t MemoryManagerx86::createAddressSpace() -{ - if(((size_t) table & 0xFFF) != 0) - return -1; - PageTableEntry* newDirectory = (PageTableEntry*) table; - newDirectory[1022] = m_pageDirectory[1022]; - newDirectory[1023] = m_pageDirectory[1023]; - return 0; -} - -void MemoryManagerx86::loadAddressSpace(physaddr_t table) -{ - -} - -int MemoryManagerx86::mapPage(void *page, physaddr_t frame, int flags) -{ - -} - -physaddr_t MemoryManagerx86::unmapPage(void *page) -{ - -} \ No newline at end of file diff --git a/src/x86/memorymanagerx86.hpp b/src/x86/memorymanagerx86.hpp deleted file mode 100644 index ed3273e..0000000 --- a/src/x86/memorymanagerx86.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MEMORYMANAGERX86_H -#define MEMORYMANAGERX86_H - -#include "../memorymanager.hpp" -#include "pagetableentry.hpp" - -class MemoryManagerx86 : public MemoryManager -{ -public: - - virtual unsigned int getPageSize() const; - - virtual physaddr_t createAddressSpace(); - - virtual void loadAddressSpace(physaddr_t table); - - virtual int mapPage(void* page, physaddr_t frame, int flags); - - virtual physaddr_t unmapPage(void* page); - -private: - - static const unsigned int pageSize = 4096; - - PageTableEntry *m_pageTables, *m_pageDirectory; - -}; - -#endif \ No newline at end of file diff --git a/src/x86/mmap.cpp b/src/x86/mmap.cpp deleted file mode 100644 index 3cddf3b..0000000 --- a/src/x86/mmap.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#include "../mmap.hpp" -#include "../kernelstate.hpp" - -class PageTableEntry { -public: - - PageTableEntry() - { - this->present = 0; - this->rw = 0; - this->usermode = 0; - this->writeThrough = 0; - this->cacheDisable = 0; - this->accessed = 0; - this->dirty = 0; - this->pat = 0; - this->global = 0; - this->shared = 0; - this->ignored = 0; - this->physicalAddress = 0; - } - - bool getAccessed() const - { - return accessed == 1; - } - - bool getCacheDisable() const - { - return cacheDisable == 1; - } - - void setCacheDisable(bool cacheDisable) - { - this->cacheDisable = cacheDisable ? 1 : 0; - } - - bool getDirty() const - { - return dirty == 1; - } - - bool getGlobal() const - { - return global == 1; - } - - void setGlobal(bool global) - { - this->global = global ? 1 : 0; - } - - bool getPat() const - { - return pat == 1; - } - - void setPat(bool pat) - { - this->pat = pat ? 1 : 0; - } - - physaddr_t getPhysicalAddress() const - { - physaddr_t physicalAddress = this->physicalAddress; - return physicalAddress << 12; - } - - physaddr_t setPhysicalAddress(physaddr_t physicalAddress) - { - this->physicalAddress = physicalAddress >> 12; - return this->physicalAddress << 12; - } - - bool getPresent() const - { - return present == 1; - } - - void setPresent(bool present) - { - this->present = present ? 1 : 0; - } - - bool getRw() const - { - return rw == 1; - } - - void setRw(bool rw) - { - this->rw = rw ? 1 : 0; - } - - bool getShared() const - { - return shared == 1; - } - - void setShared(bool shared) - { - this->shared = shared ? 1 : 0; - } - - bool getUsermode() const - { - return usermode == 1; - } - - void setUsermode(bool usermode) - { - this->usermode = usermode ? 1 : 0; - } - - bool getWriteThrough() const - { - return writeThrough == 1; - } - - void setWriteThrough(bool writeThrough) - { - this->writeThrough = writeThrough ? 1 : 0; - } - - physaddr_t operator=(physaddr_t rhs) - { - return setPhysicalAddress(rhs); - } - - PageTableEntry operator=(PageTableEntry rhs) - { - uint32_t* iThis = (uint32_t*) this; - uint32_t* iThat = (uint32_t*) &rhs; - *iThis = *iThat; - return rhs; - } - -private: - uint32_t present : 1; - uint32_t rw : 1; - uint32_t usermode : 1; - uint32_t writeThrough : 1; - uint32_t cacheDisable : 1; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t pat : 1; - uint32_t global : 1; - uint32_t shared : 1; - uint32_t ignored : 2; - uint32_t physicalAddress : 20; -}; - -int kernelns::mmap(void* start, size_t length, int flags) -{ - if((size_t) start % 4096 != 0) - return -1; - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) start / 4096; - for(int i = (int) length; i > 0; i -= 4096) - { - size_t directoryIndex = tableIndex / 1024; - if(!pageDirectory[directoryIndex].getPresent()) - { - physaddr_t newPT = State::pageAllocator.allocate(4096); - if(newPT == 0) - return -1; - pageDirectory[directoryIndex] = newPT; - pageDirectory[directoryIndex].setPresent(true); - pageDirectory[directoryIndex].setUsermode(false); - pageDirectory[directoryIndex].setRw(true); - } - if(!pageTables[tableIndex].getPresent()) - { - physaddr_t page = State::pageAllocator.allocate(4096); - pageTables[tableIndex] = page; - pageTables[tableIndex].setPresent(true); - pageTables[tableIndex].setUsermode(false); - if(flags & MMAP_RW) - pageTables[tableIndex].setRw(true); - } - tableIndex++; - } - return 0; -} - -int kernelns::mmap(void* start, physaddr_t p_start, size_t length, int flags) -{ - if((size_t) start % 4096 != 0 || p_start % 4096 != 0) - return -1; - physaddr_t page = p_start; - for(int i = (int) length; i > 0; i -= 4096) - { - if(mapPage(start, page, flags) != 0) - return -1; - page += 4096; - } - return 0; -} - -int kernelns::mapPage(void* start, physaddr_t p_start, int flags) -{ - if((size_t) start % 4096 != 0 || p_start % 4096 != 0) - return -1; - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) start / 4096; - physaddr_t page = p_start; - size_t directoryIndex = tableIndex / 1024; - if(!pageDirectory[directoryIndex].getPresent()) - { - physaddr_t newPT = State::pageAllocator.allocate(4096); - if(newPT == 0) - return -1; - pageDirectory[directoryIndex] = newPT; - pageDirectory[directoryIndex].setPresent(true); - pageDirectory[directoryIndex].setUsermode(false); - pageDirectory[directoryIndex].setRw(true); - } - if(!pageTables[tableIndex].getPresent()) - { - pageTables[tableIndex] = page; - pageTables[tableIndex].setPresent(true); - pageTables[tableIndex].setUsermode(false); - if(flags & MMAP_RW) - pageTables[tableIndex].setRw(true); - } - return 0; -} - -int kernelns::munmap(void* start, size_t length) -{ - if((size_t) start % 4096 != 0) - return -1; - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) start / 4096; - for(int i = (int) length; i > 0; i -= 4096) - { - size_t directoryIndex = tableIndex / 1024; - if(pageDirectory[directoryIndex].getPresent()) - { - pageTables[tableIndex] = 0; - pageTables[tableIndex].setPresent(false); - pageTables[tableIndex].setUsermode(false); - pageTables[tableIndex].setRw(false); - } - tableIndex++; - } - return 0; -} - -bool kernelns::isMapped(void* addr) -{ - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - size_t tableIndex = (size_t) addr / 4096; - size_t directoryIndex = tableIndex / 1024; - if(pageDirectory[directoryIndex].getPresent()) - { - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - return pageTables[tableIndex].getPresent(); - } - return false; -} - -physaddr_t kernelns::getPhysicalAddress(void* addr) -{ - PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000; - size_t tableIndex = (size_t) addr / 4096; - return pageTables[tableIndex].getPhysicalAddress() + ((size_t) addr & 0xFFF); -} - -int kernelns::createAddressSpace(void* table) -{ - if(((size_t) table & 0xFFF) != 0) - return -1; - PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000; - PageTableEntry* newDirectory = (PageTableEntry*) table; - newDirectory[1022] = pageDirectory[1022]; - newDirectory[1023] = pageDirectory[1023]; - return 0; -} - -int kernelns::loadAddressSpace(physaddr_t table) -{ - if((table & 0xFFF) != 0) - return -1; - asm("mov %0, %%cr3" - : - : "r" (table)); - return 0; -} \ No newline at end of file diff --git a/src/x86/mmgr.c b/src/x86/mmgr.c new file mode 100644 index 0000000..a12be9f --- /dev/null +++ b/src/x86/mmgr.c @@ -0,0 +1,123 @@ +#include "mmgr.h" +#include "pageallocator.h" +#include "string.h" +#include "types/status.h" +#include + +const size_t page_size = 4096; + +const size_t page_bits = 12; + +struct page_table_entry_t +{ + uint32_t present : 1; + + uint32_t rw : 1; + + uint32_t usermode : 1; + + uint32_t writeThrough : 1; + + uint32_t cacheDisable : 1; + + uint32_t accessed : 1; + + uint32_t dirty : 1; + + uint32_t pat : 1; + + uint32_t global : 1; + + uint32_t shared : 1; + + uint32_t ignored : 2; + + uint32_t physicalAddress : 20; +}; + +struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000; + +struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000; + +physaddr_t create_address_space(struct page_stack_t *page_stack) +{ + physaddr_t table = reserve_page(page_stack); + if (table == S_OUT_OF_MEMORY) + { + return S_OUT_OF_MEMORY; + } + struct page_table_entry_t buffer = page_directory[0]; + page_directory[0].physicalAddress = table >> page_bits; + asm volatile("invlpg 0xFFC00000" :: + : "memory"); + memset((void *)page_tables, 0, 1022 * 4); + page_tables[1022] = page_directory[1022]; + page_tables[1023] = page_directory[1023]; + page_directory[0] = buffer; + asm volatile("invlpg 0xFFC00000" :: + : "memory"); + return table; +} + +void load_address_space(physaddr_t table) +{ + asm volatile("mov %0, %%cr3" + : + : "r"(table) + : "memory"); +} + +int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags) +{ + if ((size_t)page % page_size != 0 || frame % page_size != 0) + { + return S_OUT_OF_BOUNDS; + } + size_t table_index = (size_t)page / page_size; + size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t)); + if (!page_directory[directory_index].present) + { + physaddr_t new_table = reserve_page(page_stack); + if (new_table == S_OUT_OF_MEMORY) + { + return S_OUT_OF_MEMORY; + } + page_directory[directory_index].physicalAddress = new_table >> page_bits; + page_directory[directory_index].present = 1; + page_directory[directory_index].usermode = 0; + page_directory[directory_index].rw = 1; + } + page_tables[table_index].physicalAddress = frame >> 12; + page_tables[table_index].present = 1; + page_tables[table_index].usermode = 1; + page_tables[table_index].rw = 1; + asm volatile("invlpg (%0)" + : + : "r"(page) + : "memory"); + return S_OK; +} + +physaddr_t unmap_page(void *page) +{ + if ((size_t)page % page_size != 0) + { + return S_OUT_OF_BOUNDS; + } + size_t table_index = (size_t)page / page_size; + size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t)); + if (!page_directory[directory_index].present || !page_tables[table_index].present) + { + return S_OUT_OF_BOUNDS; + } + else + { + physaddr_t frame = page_tables[table_index].physicalAddress << page_bits; + memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t)); + asm volatile("invlpg (%0)" + : + : "r"(page) + : "memory"); + return frame; + } +} \ No newline at end of file diff --git a/src/x86/msr.c b/src/x86/msr.c new file mode 100644 index 0000000..4182a2d --- /dev/null +++ b/src/x86/msr.c @@ -0,0 +1,17 @@ +#include "msr.h" + +void read_msr(enum msr_id_t msr_addr, uint64_t *value) +{ + uint64_t v; + asm volatile("rdmsr" + : "=edx:eax" (v) + : "ecx" (msr_addr)); + *value = v; +} + +void write_msr(enum msr_id_t msr_addr, uint64_t *value) +{ + uint64_t v = *value; + asm volatile("wrmsr" + :: "ecx"(msr_addr), "A"(v)); +} diff --git a/src/x86/msr.h b/src/x86/msr.h new file mode 100644 index 0000000..ea09f03 --- /dev/null +++ b/src/x86/msr.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +enum msr_id_t +{ + MSR_APIC_BASE = 0x1B +}; + +struct msr_apic_base_t +{ + uint64_t reserved_1 : 8; + uint64_t bsp : 1; + uint64_t reserved_2 : 1; + uint64_t x2apic_enable : 1; + uint64_t apic_global_enable : 1; + uint64_t apic_base : 52; +}; + +void read_msr(enum msr_id_t msr_addr, uint64_t *value); + +void write_msr(enum msr_id_t msr_addr, uint64_t *value); diff --git a/src/x86/multiboot2.c b/src/x86/multiboot2.c new file mode 100644 index 0000000..c692b5f --- /dev/null +++ b/src/x86/multiboot2.c @@ -0,0 +1,55 @@ +#include "multiboot2.h" +#include "stdio.h" +#include "string.h" + +void *read_multiboot_table(struct boot_info_t *boot_info, void *table) +{ + uint32_t *int_table = (uint32_t *)table; + switch (*int_table) + { + case MB_END_TAG: + return NULL; + case MB_MEMORY_MAP: ; + unsigned int tag_size = ((struct multiboot2_memory_map_t*) table)->size - 16; + unsigned int entry_size = ((struct multiboot2_memory_map_t*) table)->entry_size; + struct multiboot2_map_entry_t *entry = &((struct multiboot2_memory_map_t*) table)->entries; + while(tag_size) + { + unsigned int entry_type = + entry->type == MB_AVAILABLE ? M_AVAILABLE + : (entry->type == MB_DEFECTIVE ? M_DEFECTIVE + : M_UNAVAILABLE); + insert_region(&boot_info->map, entry->base, entry->length, entry_type); + entry = (struct multiboot2_map_entry_t*) ((void*) entry + entry_size); + tag_size -= entry_size; + } + break; + case MB_MODULE: + if(boot_info->module_count < 8) + { + boot_info->modules[boot_info->module_count].start = ((struct multiboot2_module_t*) table)->start; + boot_info->modules[boot_info->module_count].end = ((struct multiboot2_module_t*) table)->end; + strcpy(boot_info->modules[boot_info->module_count].str, ((struct multiboot2_module_t*) table)->str); + insert_region(&boot_info->map, + ((struct multiboot2_module_t*) table)->start, + ((struct multiboot2_module_t*) table)->end - ((struct multiboot2_module_t*) table)->start, + M_UNAVAILABLE); + boot_info->module_count++; + } + else + { + printf("WARNING: Too many modules, must skip one.\n"); + } + break; + case MB_BOOT_COMMAND: + strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str); + break; + case MB_BOOTLOADER: + strcpy(boot_info->bootloader, &((struct multiboot2_string_t*) table)->str); + break; + default: + break; + } + size_t size = (int_table[1] + 7) - ((int_table[1] + 7) % 8); + return table + size; +} diff --git a/src/x86/multiboot2.cpp b/src/x86/multiboot2.cpp deleted file mode 100644 index ba745b5..0000000 --- a/src/x86/multiboot2.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "multiboot2.hpp" -#include "../memorytype.hpp" - -using namespace kernelns; - -Multiboot2Info::Multiboot2Info(void* tableLocation) -{ - m_commandLine = NULL; - m_bootloader = NULL; - m_moduleCount = 0; - uint32_t* ptr = (uint32_t*) tableLocation; - ptr += 2; - while(*ptr != 0) - { - if(*ptr == (uint32_t) Tag::BootCommand) - { - m_commandLine = &reinterpret_cast(ptr)->str; - } - else if(*ptr == (uint32_t) Tag::Bootloader) - { - m_bootloader = &reinterpret_cast(ptr)->str; - } - else if(*ptr == (uint32_t) Tag::MemoryMap) - { - unsigned int tagSize = reinterpret_cast(ptr)->size - 16; - unsigned int entrySize = reinterpret_cast(ptr)->entrySize; - MemoryMapEntry* entry = &reinterpret_cast(ptr)->entries; - while(tagSize > 0) - { - unsigned int regionType = - (entry->type == (unsigned int) Multiboot2MemoryType::Available) ? (unsigned int) MemoryType::Available - : ((entry->type == (unsigned int) Multiboot2MemoryType::Defective) ? (unsigned int) MemoryType::Defective - : (unsigned int) MemoryType::Unavailable); - m_memmap.insertEntry(entry->base, entry->length, entry->type); - entry = (MemoryMapEntry*) (reinterpret_cast(entry) + entrySize); - tagSize -= entrySize; - } - } - else if(*ptr == (uint32_t) Tag::Module) - { - TagModule* moduleTag = reinterpret_cast(ptr); - m_modules[m_moduleCount] = Module(moduleTag->start, moduleTag->end, &moduleTag->str); - m_memmap.insertEntry(moduleTag->start, moduleTag->end - moduleTag->start, (unsigned int) MemoryType::Unavailable); - } - unsigned int size = (ptr[1] + 7) - ((ptr[1] + 7) % 8); - ptr += size / sizeof(uint32_t); - } -} - -Multiboot2Info::~Multiboot2Info() -{ - -} - -bool Multiboot2Info::isValid() const -{ - return true; -} - -MemoryMap& Multiboot2Info::getMemoryMap() -{ - return m_memmap; -} - -const Module* Multiboot2Info::getModules() const -{ - return m_modules; -} - -unsigned int Multiboot2Info::getModuleCount() const -{ - return m_moduleCount; -} - -const char* Multiboot2Info::getCommandLine() const -{ - return m_commandLine; -} - -const char* Multiboot2Info::getBootloaderName() const -{ - return m_bootloader; -} \ No newline at end of file diff --git a/src/x86/multiboot2.h b/src/x86/multiboot2.h new file mode 100644 index 0000000..ce65ddb --- /dev/null +++ b/src/x86/multiboot2.h @@ -0,0 +1,84 @@ +#pragma once + +#include "memorymap.h" +#include "module.h" +#include +#include + +#define module_limit 8 + +enum multiboot2_tag_types +{ + MB_END_TAG = 0, + MB_BOOT_COMMAND = 1, + MB_BOOTLOADER = 2, + MB_MODULE = 3, + MB_MEMORY_INFO = 4, + MB_BIOS_BOOT_DEVICE = 5, + MB_MEMORY_MAP = 6, + MB_VBE = 7, + MB_FRAMEBUFFER = 8, + MB_ELF_SYMBOLS = 9, + MB_APM = 10, + MB_EFI32_SYSTEM_TABLE = 11, + MB_EFI64_SYSTEM_TABLE = 12, + MB_SMBIOS = 13, + MB_ACPI10_RSDP = 14, + MB_ACPT20_RSDP = 15, + MB_NETOWRK = 16, + MB_EFI_MEMORY_MAP = 17, + MB_EFI_BOOT_SERVICES = 18, + MB_EFI32_IMAGE = 19, + MB_EFI64_IMAGE = 20, + MB_LOAD_ADDRESS = 21 +}; + +enum multiboot2_memory_types +{ + MB_AVAILABLE = 1, + MB_ACPI = 3, + MB_DEFECTIVE = 5 +}; + +struct multiboot2_string_t +{ + uint32_t type; + uint32_t size; + char str; +}; + +struct multiboot2_module_t +{ + uint32_t type; + uint32_t size; + uint32_t start; + uint32_t end; + char str; +}; + +struct multiboot2_map_entry_t +{ + uint64_t base; + uint64_t length; + uint32_t type; +}; + +struct multiboot2_memory_map_t +{ + uint32_t type; + uint32_t size; + uint32_t entry_size; + uint32_t entry_version; + struct multiboot2_map_entry_t entries; +}; + +struct boot_info_t +{ + char *bootloader; + char *parameters; + size_t module_count; + struct memory_map_t map; + struct module_t modules[module_limit]; +}; + +void *read_multiboot_table(struct boot_info_t *boot_info, void *table); diff --git a/src/x86/multiboot2.hpp b/src/x86/multiboot2.hpp deleted file mode 100644 index 73962e1..0000000 --- a/src/x86/multiboot2.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef MULTIBOOT2_H -#define MULTIBOOT2_H - -#include "../memorymap.hpp" -#include "../module.hpp" - -namespace kernelns -{ - -class Multiboot2Info -{ -public: - - enum class Tag - { - BootCommand = 1, - Bootloader = 2, - Module = 3, - MemoryInfo = 4, - BIOSBootDevice = 5, - MemoryMap = 6, - VBE = 7, - Framebuffer = 8, - ELFSymbols = 9, - APM = 10, - EFI32SystemTable = 11, - EFI64SystemTable = 12, - SMBIOS = 13, - ACPI10RSDP = 14, - ACPT20RSDP = 15, - Network = 16, - EFIMemoryMap = 17, - EFIBootServices = 18, - EFI32Image = 19, - EFI64Image = 20, - LoadAddress = 21 - }; - - enum class Multiboot2MemoryType - { - Available = 1, - ACPI = 3, - Defective = 5 - }; - - struct TagString - { - uint32_t type; - uint32_t size; - char str; - }; - - struct TagModule - { - uint32_t type; - uint32_t size; - uint32_t start; - uint32_t end; - char str; - }; - - struct MemoryMapEntry - { - uint64_t base; - uint64_t length; - uint32_t type; - }; - - struct TagMemoryMap - { - uint32_t type; - uint32_t size; - uint32_t entrySize; - uint32_t entryVersion; - MemoryMapEntry entries; - }; - - Multiboot2Info(void* tableLocation); - - ~Multiboot2Info(); - - bool isValid() const; - - MemoryMap& getMemoryMap(); - - const Module* getModules() const; - - unsigned int getModuleCount() const; - - const char* getCommandLine() const; - - const char* getBootloaderName() const; - -private: - - Module m_modules[16]; - - unsigned int m_moduleCount; - - MemoryMap m_memmap; - - char* m_commandLine; - - char* m_bootloader; - - void* m_tableLocation; - -}; - -} - -#endif \ No newline at end of file diff --git a/src/x86/pagetableentry.cpp b/src/x86/pagetableentry.cpp deleted file mode 100644 index 5e50799..0000000 --- a/src/x86/pagetableentry.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "pagetableentry.hpp" - -PageTableEntry::PageTableEntry() -{ - this->present = 0; - this->rw = 0; - this->usermode = 0; - this->writeThrough = 0; - this->cacheDisable = 0; - this->accessed = 0; - this->dirty = 0; - this->pat = 0; - this->global = 0; - this->shared = 0; - this->ignored = 0; - this->physicalAddress = 0; -} - -bool PageTableEntry::getAccessed() const -{ - return accessed == 1; -} - -bool PageTableEntry::getCacheDisable() const -{ - return cacheDisable == 1; -} - -void PageTableEntry::setCacheDisable(bool cacheDisable) -{ - this->cacheDisable = cacheDisable ? 1 : 0; -} - -bool PageTableEntry::getDirty() const -{ - return dirty == 1; -} - -bool PageTableEntry::getGlobal() const -{ - return global == 1; -} - -void PageTableEntry::setGlobal(bool global) -{ - this->global = global ? 1 : 0; -} - -bool PageTableEntry::getPat() const -{ - return pat == 1; -} - -void PageTableEntry::setPat(bool pat) -{ - this->pat = pat ? 1 : 0; -} - -physaddr_t PageTableEntry::getPhysicalAddress() const -{ - physaddr_t physicalAddress = this->physicalAddress; - return physicalAddress << 12; -} - -physaddr_t PageTableEntry::setPhysicalAddress(physaddr_t physicalAddress) -{ - this->physicalAddress = physicalAddress >> 12; - return this->physicalAddress << 12; -} - -bool PageTableEntry::getPresent() const -{ - return present == 1; -} - -void PageTableEntry::setPresent(bool present) -{ - this->present = present ? 1 : 0; -} - -bool PageTableEntry::getRw() const -{ - return rw == 1; -} - -void PageTableEntry::setRw(bool rw) -{ - this->rw = rw ? 1 : 0; -} - -bool PageTableEntry::getShared() const -{ - return shared == 1; -} - -void PageTableEntry::setShared(bool shared) -{ - this->shared = shared ? 1 : 0; -} - -bool PageTableEntry::getUsermode() const -{ - return usermode == 1; -} - -void PageTableEntry::setUsermode(bool usermode) -{ - this->usermode = usermode ? 1 : 0; -} - -bool PageTableEntry::getWriteThrough() const -{ - return writeThrough == 1; -} - -void PageTableEntry::setWriteThrough(bool writeThrough) -{ - this->writeThrough = writeThrough ? 1 : 0; -} - -physaddr_t PageTableEntry::operator=(physaddr_t rhs) -{ - return setPhysicalAddress(rhs); -} - -PageTableEntry PageTableEntry::operator=(PageTableEntry rhs) -{ - uint32_t *iThis = (uint32_t *)this; - uint32_t *iThat = (uint32_t *)&rhs; - *iThis = *iThat; - return rhs; -} \ No newline at end of file diff --git a/src/x86/pagetableentry.hpp b/src/x86/pagetableentry.hpp deleted file mode 100644 index 1a5381c..0000000 --- a/src/x86/pagetableentry.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef PAGETABLEENTRY_H -#define PAGETABLEENTRY_H - -#include "../systypes.hpp" - -class PageTableEntry { -public: - - PageTableEntry(); - - bool getAccessed() const; - - bool getCacheDisable() const; - - void setCacheDisable(bool cacheDisable); - - bool getDirty() const; - - bool getGlobal() const; - - void setGlobal(bool global); - - bool getPat() const; - - void setPat(bool pat); - - physaddr_t getPhysicalAddress() const; - - physaddr_t setPhysicalAddress(physaddr_t physicalAddress); - - bool getPresent() const; - - void setPresent(bool present); - - bool getRw() const; - - void setRw(bool rw); - - bool getShared() const; - - void setShared(bool shared); - - bool getUsermode() const; - - void setUsermode(bool usermode); - - bool getWriteThrough() const; - - void setWriteThrough(bool writeThrough); - - physaddr_t operator=(physaddr_t rhs); - - PageTableEntry operator=(PageTableEntry rhs); - -private: - - uint32_t present : 1; - - uint32_t rw : 1; - - uint32_t usermode : 1; - - uint32_t writeThrough : 1; - - uint32_t cacheDisable : 1; - - uint32_t accessed : 1; - - uint32_t dirty : 1; - - uint32_t pat : 1; - - uint32_t global : 1; - - uint32_t shared : 1; - - uint32_t ignored : 2; - - uint32_t physicalAddress : 20; - -}; - -#endif \ No newline at end of file diff --git a/src/x86/putc.c b/src/x86/putc.c new file mode 100644 index 0000000..854751f --- /dev/null +++ b/src/x86/putc.c @@ -0,0 +1,68 @@ +#include "stdio.h" +#include + +enum vga_color_t { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +__attribute__ ((packed)) +struct cell_t +{ + char c; + char fg : 4; + char bg : 4; +}; + +struct cell_t *screen = (struct cell_t*)0xFF8B8000; +size_t cursor = 0; + +const size_t tab_width = 4; +const size_t line_width = 80; + +int putchar(int c) +{ + switch(c) + { + case '\n': + cursor += line_width; + cursor -= cursor % line_width; + break; + case '\t': + cursor += tab_width; + cursor -= cursor % tab_width; + break; + case '\r': + cursor -= line_width - 1; + cursor += line_width - (cursor % line_width); + break; + default: + screen[cursor].c = (char) c; + cursor++; + } + return c; +} + +int puts(const char *str) +{ + while(*str) + { + putchar(*str); + str++; + } + return 0; +} \ No newline at end of file diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c new file mode 100644 index 0000000..0b6ec8c --- /dev/null +++ b/src/x86/quark_x86.c @@ -0,0 +1,102 @@ +#include "kernel.h" +#include "pageallocator.h" +#include "multiboot2.h" +#include "memorymap.h" +#include "apic.h" +#include "interrupts.h" +#include "msr.h" +#include "stdio.h" +#include "string.h" +#include "module.h" +#include "isr.h" +#include +#include + +extern int _kernel_end; + +struct apic_registers_t volatile *apic_registers; + +int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) +{ + for (int i = 0; i < 1024; i++) + { + uint32_t pte = i * 4096 + 3; + table[i] = pte; + identityTable[i] = pte; + } + directory[0] = ((uint32_t)identityTable) + 3; + directory[1022] = ((uint32_t)table) + 3; + directory[1023] = ((uint32_t)directory) + 3; + asm("mov %0, %%cr3" + : + : "r"(directory)); + asm("mov %%cr0, %%eax \n" + "or $0x80010000, %%eax \n" + "mov %%eax, %%cr0" + : + : + : "eax"); + return 0; +} + +int initialize(void *multiboot_info) +{ + static struct interrupt_descriptor_t idt[256]; + static struct page_stack_t page_stack; + static struct kernel_t kernel; + struct memory_region_t map_array[16]; + char bootloader_name[64]; + char kernel_parameters[64]; + struct boot_info_t boot_info = { + .bootloader = bootloader_name, + .parameters = kernel_parameters, + .module_count = 0, + .map = { + .array = map_array, + .size = 0, + .capacity = 16}}; + multiboot_info += 8; + while (multiboot_info != NULL) + { + multiboot_info = read_multiboot_table(&boot_info, multiboot_info); + } + insert_region(&boot_info.map, 0, 1 << 22, M_UNAVAILABLE); + printf("Type\t\tLocation\t\tSize\n"); + for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++) + { + printf("%i\t\t\t%08x\t\t%u\n", boot_info.map.array[i].type, boot_info.map.array[i].location, boot_info.map.array[i].size); + } + page_stack.base_pointer = (physaddr_t*)0xFFC00000; + page_stack.stack_pointer = (physaddr_t*)0xFFC00000; + page_stack.limit_pointer = (physaddr_t*)0xFF900000; + initialize_page_stack(&page_stack, &boot_info.map, 4096); + for(int i = 0; i < boot_info.module_count; i++) + { + load_module(&kernel, &boot_info.modules[i]); + } + // TODO: setup IDT + memset(idt, 0, sizeof(struct interrupt_descriptor_t) * 256); + create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0); + lidt(idt); + + // TODO: setup APIC + asm volatile( + "mov $0xFF, %%al;" + "outb %%al, $0xA1;" + "outb %%al, $0x21;" + ::: "al" + ); + apic_enable(); + struct msr_apic_base_t msr; + read_msr(MSR_APIC_BASE, (uint64_t*)&msr); + msr.apic_base = (size_t) &_kernel_end >> 12; + write_msr(MSR_APIC_BASE, (uint64_t*)&msr); + printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); + apic_registers = (struct apic_registers_t*) (msr.apic_base << 12); + // TODO: enter first process +} diff --git a/src/x86/tty.cpp b/src/x86/tty.cpp deleted file mode 100644 index 8ee9929..0000000 --- a/src/x86/tty.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include "tty.hpp" - -kernelns::TTY::TTY(char* vga) -{ - this->vga = vga; - this->cursor = 0; - this->width = 0; - this->base = 10; -} - -kernelns::TTY& kernelns::TTY::operator<<(kernelns::TTY::Format fmt) -{ - switch(fmt) - { - case Binary: - base = 2; - break; - case Decimal: - base = 10; - break; - case Hex: - base = 16; - break; - } -} - -kernelns::TTY& kernelns::TTY::operator<<(const char* str) -{ - return printString(str); -} - -kernelns::TTY& kernelns::TTY::operator<<(unsigned int n) -{ - return printNumber(n, base, width); -} - -kernelns::TTY& kernelns::TTY::operator<<(int n) -{ - return printNumber((unsigned int) n, base, width); -} - -kernelns::TTY& kernelns::TTY::operator<<(void* n) -{ - return printNumber((unsigned int) n, 16, 8); -} - -kernelns::TTY& kernelns::TTY::operator<<(char c) -{ - return putChar(c); -} - -void kernelns::TTY::setWidth(size_t width) -{ - this->width = width; -} - -size_t kernelns::TTY::getWidth() -{ - return width; -} - -void kernelns::TTY::clear() -{ - for(int i = 0; i < 80*25; i++) - { - vga[i * 2] = ' '; - } - cursor = 0; -} - -kernelns::TTY& kernelns::TTY::printNumber(unsigned int n, size_t base, - size_t width) -{ - const char* digits = "0123456789ABCDEF"; - char str[33]; - size_t i = 1; - do - { - str[i] = digits[n % base]; - n /= base; - i++; - } while(n > 0); - while(i <= width) - { - str[i] = '0'; - i++; - } - str[0] = '\0'; - for(char* s = str + (i - 1); *s; s--) - { - putChar(*s); - } - return *this; -} - -kernelns::TTY& kernelns::TTY::printString(const char* str) -{ - while(*str) - { - putChar(*str); - str++; - } - return *this; -} - -kernelns::TTY& kernelns::TTY::putChar(char c) -{ - switch(c) - { - case '\n': - cursor = (cursor + 80) - (cursor % 80); - break; - case '\t': - cursor = (cursor + 4) - (cursor % 4); - break; - case '\r': - cursor -= cursor % 160; - break; - default: - vga[cursor * 2] = c; - cursor++; - } - return *this; -} diff --git a/src/x86/tty.hpp b/src/x86/tty.hpp deleted file mode 100644 index 72bacf7..0000000 --- a/src/x86/tty.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef TTY_H_ -#define TTY_H_ - -#include - -namespace kernelns -{ - -class TTY -{ -public: - - enum Format - { - Binary, - Decimal, - Hex - }; - - TTY(char* vga); - - TTY& operator<<(Format fmt); - - TTY& operator<<(const char* str); - - TTY& operator<<(unsigned int n); - - TTY& operator<<(int n); - - TTY& operator<<(void* n); - - TTY& operator<<(char c); - - void setWidth(size_t width); - - size_t getWidth(); - - void clear(); - -private: - - TTY& printNumber(unsigned int n, size_t base, size_t width); - - TTY& printString(const char* str); - - TTY& putChar(char c); - - char* vga; - - int cursor; - - size_t width; - - size_t base; - -}; - -} - -#endif