From 44523705a3688bb4e5ee8ceae012eceaf0d04132 Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 26 Nov 2019 19:17:38 -0600 Subject: [PATCH 01/10] Fixed page fault on bootup --- src/entry.S | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/entry.S b/src/entry.S index b0dd842..195d3d3 100644 --- a/src/entry.S +++ b/src/entry.S @@ -26,41 +26,76 @@ _start: movb $64, 0xB8000 mov $0, %ecx -1: mov %ecx, %eax +1: + # Generate a page table entry pointing to a page in the kernel binary + mov %ecx, %eax mov $4096, %edx mul %edx add $PHYSICAL_BASE, %eax or $3, %eax + + # Load the address of the temporary page table and translate it to a physical address mov $_tempPgTable, %edi + sub $BASE_DIFF, %edi + + # Save the PTE into an entry in the temporary page table mov %eax, (%edi, %ecx, 4) + + # Load the address of the identity map and translate it to a physical address mov $_tempIdentityMap, %edi + sub $BASE_DIFF, %edi + + # Save the PTE into an entry in the identity map mov %eax, 1024(%edi, %ecx, 4) + + # Increment count and loop inc %ecx cmp $IMAGE_SIZE, %ecx jne 1b + # Load the physical address of the identity map, and generate a PDE mov $_tempIdentityMap, %eax + sub $BASE_DIFF, %eax or $3, %eax - mov %eax, (_tempPgDir) + # Load the physical address of the page directory + mov $_tempPgDir, %edi + sub $BASE_DIFF, %edi + + # Save the PDE to the first element in the page directory + mov %eax, (%edi) + + # Load the physical address of the temporary page table, and generate a PDE mov $_tempPgTable, %eax + sub $BASE_DIFF, %eax or $3, %eax - mov %eax, (_tempPgDir + 3072) - mov $_tempPgDir, %eax - mov %eax, %cr3 + # Save the PDE to the entry corresponding to 0xC0000000 + mov %eax, 3072(%edi) + # Load the physical address of the page directory into CR3 + mov %edi, %cr3 + + # Enable paging mov %cr0, %eax or $0x80010000, %eax mov %eax, %cr0 + + # Jump into mapped kernel binary lea 2f, %eax jmp *%eax -2: movl $0, (_tempIdentityMap) +2: + # Delete PDE corresponding to identity map. We shouldn't need it anymore. + movl $0, (_tempIdentityMap) + + # Reload page tables mov %cr3, %eax mov %eax, %cr3 + # Initialize stack mov $stackTop, %esp + # Call main function call main _err: From d3ba3c1d2aedecceceb6c4f3e4a72fd1679bbb93 Mon Sep 17 00:00:00 2001 From: Nathan Date: Wed, 1 Jul 2020 15:47:56 -0500 Subject: [PATCH 02/10] Wrote proper Makefile --- .gitignore | 9 +- Makefile | 26 ++++ README.md | 0 src/Makefile | 16 --- src/addressspace.cpp | 27 ++++ src/addressspace.h | 36 ++++++ src/bitmap.h | 0 src/buddyallocator.cpp | 221 ++++++++++++++++++++++++++++++++ src/buddyallocator.h | 94 ++++++++++++++ src/cstring.cpp | 0 src/cstring.h | 0 src/entry.S | 26 +++- src/error.cpp | 0 src/error.h | 0 src/errortype.h | 0 src/linker.ld | 36 ++++++ src/math.cpp | 0 src/math.h | 0 src/memoryallocator.h | 58 +++++++++ src/multiboot2header.S | 0 src/pagetableentry.cpp | 0 src/pagetableentry.h | 0 src/physicalmemoryallocator.cpp | 202 ----------------------------- src/physicalmemoryallocator.h | 90 ------------- src/quarkkernel.cpp | 19 ++- src/tty.cpp | 125 ++++++++++++++++++ src/tty.h | 35 +++++ 27 files changed, 701 insertions(+), 319 deletions(-) mode change 100644 => 100755 .gitignore create mode 100644 Makefile mode change 100644 => 100755 README.md delete mode 100644 src/Makefile create mode 100644 src/addressspace.cpp create mode 100755 src/addressspace.h mode change 100644 => 100755 src/bitmap.h create mode 100755 src/buddyallocator.cpp create mode 100755 src/buddyallocator.h mode change 100644 => 100755 src/cstring.cpp mode change 100644 => 100755 src/cstring.h mode change 100644 => 100755 src/entry.S mode change 100644 => 100755 src/error.cpp mode change 100644 => 100755 src/error.h mode change 100644 => 100755 src/errortype.h create mode 100755 src/linker.ld mode change 100644 => 100755 src/math.cpp mode change 100644 => 100755 src/math.h create mode 100755 src/memoryallocator.h mode change 100644 => 100755 src/multiboot2header.S mode change 100644 => 100755 src/pagetableentry.cpp mode change 100644 => 100755 src/pagetableentry.h delete mode 100644 src/physicalmemoryallocator.cpp delete mode 100644 src/physicalmemoryallocator.h mode change 100644 => 100755 src/quarkkernel.cpp create mode 100644 src/tty.cpp create mode 100644 src/tty.h diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 50372c5..d0b6b8e --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -bin/qkernel -bin/*.o -bin/*~ \ No newline at end of file +bin/* +src/*.o +quark.iso +src/*~ +*~ +rootfs \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..77f81a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ + src/cstring.o src/error.o src/pagetableentry.o src/multiboot2header.o\ + src/entry.o src/quarkkernel.o +link_script = src/linker.ld +quark_bin = qkernel +quark_img = quark.iso + +CXX = i686-elf-g++ +CC = i686-elf-gcc + +CPPFLAGS = -ffreestanding -O2 -Wall -fno-exceptions -fno-rtti -ggdb + +.PHONY: all +all: $(quark_img) + +$(quark_img): bin/$(quark_bin) + cp bin/$(quark_bin) rootfs/apps + grub-mkrescue -o $@ rootfs + +bin/$(quark_bin): $(objs) + mkdir -p bin/ + $(CXX) -o $@ -T $(link_script) -ffreestanding -nostdlib -O0 $^ -lgcc + +.PHONY: clean +clean: + rm -f $(objs) bin/$(quark_bin) $(quark_img) diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 82cf391..0000000 --- a/src/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -objs = math.o cstring.o error.o pagetableentry.o physicalmemoryallocator.o multiboot2header.o entry.o quarkkernel.o -link_script = linker.ld -quark_bin = qkernel - -CXX = i686-elf-g++ -CC = i686-elf-gcc - -CPPFLAGS += -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti - -all: $(objs) - echo $(PATH) - i686-elf-g++ -o $(quark_bin) -T $(link_script) -ffreestanding -nostdlib -O2 $(objs) -lgcc - -clean: - rm *.o - rm -f $(quark_bin) diff --git a/src/addressspace.cpp b/src/addressspace.cpp new file mode 100644 index 0000000..a62b903 --- /dev/null +++ b/src/addressspace.cpp @@ -0,0 +1,27 @@ +#include "addressspace.h" + +qkernel::AddressSpace::AddressSpace(MemoryAllocator& malloc) + : malloc(malloc) +{ + this->pageTables = (PageTableEntry*) 0xFFC00000; +} + +void* qkernel::AddressSpace::mmap(void* start, size_t length) +{ + +} + +void qkernel::AddressSpace::munmap(void* start, size_t length) +{ + +} + +void* qkernel::AddressSpace::getPhysicalAddress(void* virtualAddress) const +{ + size_t index = (size_t) virtualAddress / 4096; + PageTableEntry pte = pageTables[index]; + if(pte.getPresent()) + return (void*) pte.getPhysicalAddress(); + else + return (void*) 0; +} diff --git a/src/addressspace.h b/src/addressspace.h new file mode 100755 index 0000000..276a6c7 --- /dev/null +++ b/src/addressspace.h @@ -0,0 +1,36 @@ +#ifndef SRC_ADDRESSSPACE_H_ +#define SRC_ADDRESSSPACE_H_ + +#include + +#include "memoryallocator.h" +#include "pagetableentry.h" + +namespace qkernel { + +class AddressSpace { +public: + + AddressSpace(MemoryAllocator& malloc); + + void* mmap(void* start, size_t length); + + void munmap(void* start, size_t length); + + void* getPhysicalAddress(void* virtualAddress) const; + +private: + + MemoryAllocator& malloc; + + /** + * Array of 1024 page tables, each containing 1024 entries. + * The last table represents the page directory. + */ + PageTableEntry* pageTables; + +}; + +} /* namespace qkernel */ + +#endif diff --git a/src/bitmap.h b/src/bitmap.h old mode 100644 new mode 100755 diff --git a/src/buddyallocator.cpp b/src/buddyallocator.cpp new file mode 100755 index 0000000..a2462b0 --- /dev/null +++ b/src/buddyallocator.cpp @@ -0,0 +1,221 @@ +#include "buddyallocator.h" +#include "math.h" + +#define roundUp(n, m) ((n % m == 0) ? n : (n + m - (n % m))) + +qkernel::BuddyAllocator::BuddyAllocator() +{ + +} + +qkernel::BuddyAllocator::BuddyAllocator(void* heapLocation, char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight) +{ + this->heapLocation = heapLocation; + this->bitmap = bitmap; + this->blockSize = blockSize; + this->blockCount = blockCount; + this->treeHeight = treeHeight; + for(size_t i = 0; i <= treeHeight; i++) + { + for(size_t j = 0; j < (blockCount >> i); j++) + { + if(i < treeHeight) + reserveNode(i, j); + else + freeNode(i, j); + } + } +} + +void* qkernel::BuddyAllocator::allocate(size_t size) +{ + size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); + if(height > treeHeight) // Requested block size is greater than maximum + { + return NULL; + } + else + { + size_t index = findFreeBlock(height); + if(index == INVALID) // Failed to find a big enough free block; out of memory + { + return NULL; + } + else + { + reserveNode(height, index); + return nodeToAddress(height, index); + } + } +} + +void qkernel::BuddyAllocator::free(void* location, size_t size) +{ + size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); + if(height <= treeHeight) + { + size_t index = addressToNode(height, location); + freeNode(height, index); + if(isFree(height, getBuddy(index))) + { + merge(height, index); + } + } +} + +size_t qkernel::BuddyAllocator::freeBlocks() const +{ + size_t count = 0; + for(int j = 0; j < blockCount; j++) + { + if(isFree(0, j)) + { + count++; + } + } + return count; +} + +size_t qkernel::BuddyAllocator::maxAllocationSize() const +{ + for(int i = treeHeight; i >= 0; i--) + { + for(int j = 0; j < (blockCount >> i); j++) + { + if(isFree(i, j)) + { + return 1 << i; + } + } + } + return 0; +} + +size_t qkernel::BuddyAllocator::getBlockSize() const +{ + return blockSize; +} + +size_t qkernel::BuddyAllocator::getHeapSize() const +{ + return blockCount; +} + +void* qkernel::BuddyAllocator::getHeapLocation() const +{ + return heapLocation; +} + +size_t qkernel::BuddyAllocator::findFreeBlock(size_t height) +{ + for(int i = 0; i < (blockCount >> height); i++) + { + if(isFree(height, i)) + { + return i; + } + } + if(height < treeHeight) + { + size_t parentIndex = findFreeBlock(height + 1); + if(parentIndex != INVALID) + { + return split(height + 1, parentIndex); + } + } + return INVALID; +} + +size_t qkernel::BuddyAllocator::split(size_t height, size_t index) +{ + if(height > 0 && isFree(height, index)) + { + reserveNode(height, index); + freeNode(height - 1, getChild(index)); + freeNode(height - 1, getBuddy(getChild(index))); + return getChild(index); + } + else + { + return INVALID; + } +} + +size_t qkernel::BuddyAllocator::merge(size_t height, size_t index) +{ + if(isFree(height, index) && isFree(height, getBuddy(index)) && height < treeHeight) + { + reserveNode(height, index); + reserveNode(height, getBuddy(index)); + freeNode(height + 1, getParent(index)); + if((height + 1) < treeHeight) + { + if(isFree(height + 1, getBuddy(getParent(index)))) + { + return merge(height + 1, getParent(index)); + + } + } + return getParent(index); + } + else + { + return INVALID; + } +} + +size_t qkernel::BuddyAllocator::getBuddy(size_t index) +{ + return index ^ 1; +} + +size_t qkernel::BuddyAllocator::getParent(size_t index) +{ + return index / 2; +} + +size_t qkernel::BuddyAllocator::getChild(size_t index) +{ + return index * 2; +} + +void* qkernel::BuddyAllocator::nodeToAddress(size_t height, size_t index) const +{ + char* base = (char*) heapLocation; + return reinterpret_cast(base + index * (blockSize << height)); +} + +size_t qkernel::BuddyAllocator::addressToNode(size_t height, void* location) const +{ + size_t offset = (char*) location - (char*) heapLocation; + return offset / (blockSize << height); +} + +void qkernel::BuddyAllocator::reserveNode(size_t height, size_t index) +{ + size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + bit += index; + bitmap[bit / 8] |= 1 << (bit % 8); +} + +void qkernel::BuddyAllocator::freeNode(size_t height, size_t index) +{ + size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + bit += index; + bitmap[bit / 8] &= ~(1 << (bit % 8)); +} + +bool qkernel::BuddyAllocator::isFree(size_t height, size_t index) const +{ + size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + bit += index; + char data = bitmap[bit / 8] & (1 << (bit % 8)); + if(data == 0) + { + return true; + } + else + { + return false; + } +} diff --git a/src/buddyallocator.h b/src/buddyallocator.h new file mode 100755 index 0000000..f14b7a8 --- /dev/null +++ b/src/buddyallocator.h @@ -0,0 +1,94 @@ +#ifndef BUDDYALLOCATOR_H_ +#define BUDDYALLOCATOR_H_ + +#include "memoryallocator.h" + +namespace qkernel +{ + +class BuddyAllocator : public MemoryAllocator +{ +public: + + BuddyAllocator(); + + BuddyAllocator(void* heapLocation, char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight); + + /** + * Allocate a block of memory containing at least 'size' bytes. Rounds up to the nearest + * power of 2 times the size of a block. + */ + virtual void* allocate(size_t size); + + /** + * Free the region of memory starting at 'location' and containing 'size' bytes. + */ + virtual void free(void* location, size_t size); + + /** + * @returns the total number of free blocks of memory. + */ + virtual size_t freeBlocks() const; + + /** + * @returns the size in blocks of the largest possible allocation that will not + * fail due to lack of memory. + */ + virtual size_t maxAllocationSize() const; + + /** + * @returns the size in bytes of a single block. + */ + virtual size_t getBlockSize() const; + + /** + * @returns the total number of blocks managed by this memory allocator. + */ + virtual size_t getHeapSize() const; + + /** + * @returns a pointer to the beginning of the heap managed by this memory allocator. + */ + virtual void* getHeapLocation() const; + +private: + + static const size_t INVALID = (size_t) -1; + + void* heapLocation; + + char* bitmap; + + size_t blockSize; + + size_t blockCount; + + size_t treeHeight; + + size_t findFreeBlock(size_t height); + + size_t split(size_t height, size_t index); + + size_t merge(size_t height, size_t index); + + size_t getBuddy(size_t index); + + size_t getParent(size_t index); + + size_t getChild(size_t index); + + void* nodeToAddress(size_t height, size_t index) const; + + size_t addressToNode(size_t height, void* location) const; + + void reserveNode(size_t height, size_t index); + + void freeNode(size_t height, size_t index); + + bool isFree(size_t height, size_t index) const; + +}; + +} + +#endif diff --git a/src/cstring.cpp b/src/cstring.cpp old mode 100644 new mode 100755 diff --git a/src/cstring.h b/src/cstring.h old mode 100644 new mode 100755 diff --git a/src/entry.S b/src/entry.S old mode 100644 new mode 100755 index 195d3d3..5e8ccf8 --- a/src/entry.S +++ b/src/entry.S @@ -1,5 +1,5 @@ .section .multiboot -.include "multiboot2header.S" +.include "src/multiboot2header.S" .section .bss @@ -14,7 +14,7 @@ _tempPgDir: _tempIdentityMap: .skip 4096 _tempPgTable: -.skip 4096 +.skip 8192 .section .text .global _start @@ -73,9 +73,25 @@ _start: # Save the PDE to the entry corresponding to 0xC0000000 mov %eax, 3072(%edi) - # Load the physical address of the page directory into CR3 - mov %edi, %cr3 + # Add another PDE for extra mappings the kernel needs + add $4096, %eax + mov %eax, 3076(%edi) + + # Set the last entry in the page directory to point to the page directory itself + or $3, %edi + mov %edi, 4092(%edi) + # Map VGA memory into the address space + mov $_tempPgTable, %edi + sub $BASE_DIFF, %edi + mov $0xB8003, %eax + mov %eax, 4096(%edi) + + # Load the physical address of the page directory into CR3 + mov $_tempPgDir, %edi + sub $BASE_DIFF, %edi + mov %edi, %cr3 + # Enable paging mov %cr0, %eax or $0x80010000, %eax @@ -95,6 +111,8 @@ _start: # Initialize stack mov $stackTop, %esp + push %ebx + # Call main function call main diff --git a/src/error.cpp b/src/error.cpp old mode 100644 new mode 100755 diff --git a/src/error.h b/src/error.h old mode 100644 new mode 100755 diff --git a/src/errortype.h b/src/errortype.h old mode 100644 new mode 100755 diff --git a/src/linker.ld b/src/linker.ld new file mode 100755 index 0000000..713d4d7 --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,36 @@ +ENTRY(_start) + +SECTIONS +{ + . = 0xC0000000; + VIRTUAL_BASE = .; + PHYSICAL_BASE = 0x100000; + BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; + + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + + LOAD_START = ADDR(.text) - (VIRTUAL_BASE - PHYSICAL_BASE); + LOAD_END = ADDR(.data) + SIZEOF(.data) - (VIRTUAL_BASE - PHYSICAL_BASE); + BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE); + IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096; +} diff --git a/src/math.cpp b/src/math.cpp old mode 100644 new mode 100755 diff --git a/src/math.h b/src/math.h old mode 100644 new mode 100755 diff --git a/src/memoryallocator.h b/src/memoryallocator.h new file mode 100755 index 0000000..d420849 --- /dev/null +++ b/src/memoryallocator.h @@ -0,0 +1,58 @@ +#ifndef __MEMORYALLOCATOR_H_ +#define __MEMORYALLOCATOR_H_ + +#include + +namespace qkernel +{ + +/** + * Interface for a dymanic memory allocator. + */ +class MemoryAllocator +{ +public: + + /** + * Allocate a block of memory containing 'size' bytes. May round up + * depending on the implementation. + */ + virtual void* allocate(size_t size) = 0; + + /** + * Free the region of memory starting at 'location' and containing 'size' bytes. + */ + virtual void free(void* location, size_t size) = 0; + + /** + * @returns the total number of free blocks of memory. + */ + virtual size_t freeBlocks() const = 0; + + /** + * @returns the size in blocks of the largest possible allocation that will not + * fail due to lack of memory. + */ + virtual size_t maxAllocationSize() const = 0; + + /** + * @returns the size in bytes of a single block. + */ + virtual size_t getBlockSize() const = 0; + + /** + * @returns the total number of blocks managed by this memory allocator. + */ + virtual size_t getHeapSize() const = 0; + + /** + * @returns a pointer to the beginning of the heap managed by this memory allocator. + */ + virtual void* getHeapLocation() const = 0; + + +}; + +} + +#endif diff --git a/src/multiboot2header.S b/src/multiboot2header.S old mode 100644 new mode 100755 diff --git a/src/pagetableentry.cpp b/src/pagetableentry.cpp old mode 100644 new mode 100755 diff --git a/src/pagetableentry.h b/src/pagetableentry.h old mode 100644 new mode 100755 diff --git a/src/physicalmemoryallocator.cpp b/src/physicalmemoryallocator.cpp deleted file mode 100644 index 911a2f4..0000000 --- a/src/physicalmemoryallocator.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * PhysicalMemoryAllocator.cpp - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#include "physicalmemoryallocator.h" -#include "math.h" -#include "error.h" - -namespace qkernel { - -void* const PhysicalMemoryAllocator::nullPtr = (void*) -1; - -PhysicalMemoryAllocator::PhysicalMemoryAllocator() -{ - for(size_t i = 0; i <= treeHeight; i++) - { - memoryMaps[i] = Bitmap(!available); - } - memoryMaps[treeHeight][0] = available; -} - -PhysicalMemoryAllocator::~PhysicalMemoryAllocator() -{ - // TODO Auto-generated destructor stub -} - -void* PhysicalMemoryAllocator::allocate(uint32_t pages) -{ - uint32_t height = ilog2(pages, true); - if(height >= treeHeight) // We can't allocate the whole address space at once! - { - return (void*) nullPtr; - } - - uint32_t index = findFreeBlock(height); - if(index != nullIndex) - { - memoryMaps[height][index] = !available; - return nodeToAddress(height, index); - } - else - { - return nullPtr; - } -} - -void PhysicalMemoryAllocator::free(void* location, uint32_t pages) -{ - uint32_t height = ilog2(pages, true); - if(height >= treeHeight || reinterpret_cast(location) % (4096 * pages) != 0) // We can't free the whole address space at once! - { - return; - } - - uint32_t index = addressToNode(height, location); - memoryMaps[height][index] = available; - - if(memoryMaps[height][getBuddy(index)] == available) - { - merge(height, index); - } -} - -uint32_t PhysicalMemoryAllocator::totalFreePages() -{ - uint32_t count = 0; - for(size_t i = 0; i <= treeHeight; i++) - { - count += (1 << i) * memoryMaps[i].count(); - } - return count; -} - -uint32_t PhysicalMemoryAllocator::largestFreeBlock() -{ - for(size_t i = treeHeight; i >= 0; i--) - { - if(memoryMaps[i].any()) - { - return 1 << i; - } - } -} - -uint32_t PhysicalMemoryAllocator::findFreeBlock(uint32_t height) -{ - if(memoryMaps[height].none()) - { - if(height == treeHeight) - { - lastError = Error(ErrorType::outOfMemory, "Out of memory"); - return nullIndex; - } - else - { - uint32_t parentIndex = findFreeBlock(height + 1); - if(parentIndex == (uint32_t) -1) - { - lastError = Error(ErrorType::outOfMemory, "Out of memory"); - return nullIndex; - } - split(height + 1, parentIndex); - } - - } - for(size_t index = 0; index < nodesAtHeight(height); index++) - { - if(memoryMaps[height][index] == available) - { - return index; - } - } - lastError = Error(ErrorType::illegalState, "There were still no free blocks after splitting larger ones!"); - return nullIndex; -} - -uint32_t PhysicalMemoryAllocator::merge(uint32_t height, uint32_t index) -{ - if(height == treeHeight) - { - lastError = Error(ErrorType::outOfBounds, "Attempted to merge root node"); - return nullIndex; - } - - if(memoryMaps[height][index] == 0 && memoryMaps[height][getBuddy(index)] == 0) - { - memoryMaps[height][index] = !available; - memoryMaps[height][getBuddy(index)] = !available; - memoryMaps[height + 1][getParent(index)] = available; - if(height + 1 < 20) - { - if(memoryMaps[height + 1][getBuddy(getParent(index))] == available) - { - return merge(height + 1, getParent(index)); - } - } - return getParent(index); - } - else - { - lastError = Error(ErrorType::invalidArgument, "Attempted to merge a node that is in use"); - return nullIndex; - } -} - -uint32_t PhysicalMemoryAllocator::split(uint32_t height, uint32_t index) -{ - if(height == 0) - { - lastError = Error(ErrorType::outOfBounds, "Attempted to split leaf node"); - return nullIndex; - } - - if(memoryMaps[height][index] == available) - { - memoryMaps[height][index] = !available; - memoryMaps[height - 1][getChild(index)] = available; - memoryMaps[height - 1][getBuddy(getChild(index))] = available; - return getChild(index); - } - else - { - lastError = Error(ErrorType::invalidArgument, "Attempted to split node currently in use"); - return nullIndex; - } -} - -uint32_t PhysicalMemoryAllocator::getBuddy(uint32_t index) -{ - return index ^ 1; -} - -uint32_t PhysicalMemoryAllocator::getParent(uint32_t index) -{ - return (index - index % 2) / 2; -} - -uint32_t PhysicalMemoryAllocator::getChild(uint32_t index) -{ - return index * 2; -} - -void* PhysicalMemoryAllocator::nodeToAddress(uint32_t height, uint32_t index) -{ - return reinterpret_cast(index * 4096 * (1 << height)); -} - -uint32_t PhysicalMemoryAllocator::nodesAtHeight(uint32_t height) -{ - return treeLeaves / (1 << height); -} - -uint32_t PhysicalMemoryAllocator::addressToNode(uint32_t height, - void* address) -{ - return reinterpret_cast(address) / (4096 * (1 << height)); -} - -} /* namespace qkernel */ diff --git a/src/physicalmemoryallocator.h b/src/physicalmemoryallocator.h deleted file mode 100644 index 11b0dc0..0000000 --- a/src/physicalmemoryallocator.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * PhysicalMemoryAllocator.h - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#ifndef PHYSICALMEMORYALLOCATOR_H_ -#define PHYSICALMEMORYALLOCATOR_H_ - -#include -#include -#include "bitmap.h" - -namespace qkernel { - -class PhysicalMemoryAllocator { -public: - - static void* const nullPtr; - - PhysicalMemoryAllocator(); - - ~PhysicalMemoryAllocator(); - - void* allocate(uint32_t pages); - - void free(void* location, uint32_t pages); - - uint32_t totalFreePages(); - - uint32_t largestFreeBlock(); - -private: - - static const uint32_t nullIndex = (uint32_t) -1; - - static const bool available = true; - - static const size_t treeHeight = 20; - - static const size_t treeLeaves = 1024 * 1024; - - Bitmap memoryMaps[treeHeight + 1]; - - /** - * Searches nodes of the given height for an available block. If none is - * present, recursively splits higher nodes until one is. - * - * @param height The height of the desired node. - * @returns the index of the located node - */ - uint32_t findFreeBlock(uint32_t height); - - /** - * Merges a pair of buddies that have both become available. Recurses if - * the buddy of the new block is available. - * - * @param height The height of the blocks to merge. - * @param index The index of one of the buddies to be merged. - */ - uint32_t merge(uint32_t height, uint32_t index); - - /** - * Splits a block into a pair of buddies, making the original unavailable. - * - * @param height The height of the block to split. - * @param index The index of the block to split. - * - * @returns the index of the first of the pair of new blocks. - */ - uint32_t split(uint32_t height, uint32_t index); - - uint32_t getBuddy(uint32_t index); - - uint32_t getParent(uint32_t index); - - uint32_t getChild(uint32_t index); - - uint32_t nodesAtHeight(uint32_t height); - - void* nodeToAddress(uint32_t height, uint32_t index); - - uint32_t addressToNode(uint32_t height, void* address); - -}; - -} /* namespace qkernel */ - -#endif /* PHYSICALMEMORYALLOCATOR_H_ */ diff --git a/src/quarkkernel.cpp b/src/quarkkernel.cpp old mode 100644 new mode 100755 index 17aa0fd..9f9cdbc --- a/src/quarkkernel.cpp +++ b/src/quarkkernel.cpp @@ -1,13 +1,24 @@ #include #include +#include "tty.h" + #if __STDC_HOSTED__ == 1 || __i686__ != 1 #error "ERROR: This program must be compiled for a freestanding environment, and currently only supports the i686 target." #endif -void main() +#include "buddyallocator.h" + +using namespace qkernel; + +void main(void* bootInfo) { - int x = 2; - x -= 1; - return; + char* vga = (char*) 0xC0400000; + TTY tty(vga); + tty << "--Quark Kernel--\n"; + tty << "Successfully enabled paging. Kernel image mapped to 0xC0000000.\n"; + tty << "Nothing left to do. Hanging.\n"; + tty << 18542; + char c = 'b'; + return; } diff --git a/src/tty.cpp b/src/tty.cpp new file mode 100644 index 0000000..191304d --- /dev/null +++ b/src/tty.cpp @@ -0,0 +1,125 @@ +#include +#include "tty.h" + +qkernel::TTY::TTY(char* vga) +{ + this->vga = vga; + this->cursor = 0; +} + +qkernel::TTY& qkernel::TTY::operator<<(const char* str) +{ + while(*str) + { + switch(*str) + { + 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] = *str; + cursor++; + } + str++; + } + return *this; +} + +qkernel::TTY& qkernel::TTY::operator<<(int n) +{ + if(n == 0) + { + operator<<('0'); + return *this; + } + + int sign = n > 0 ? 1 : -1; + if(sign == -1) operator<<('-'); + + int quotient; + bool showZeros = false; + for(int divisor = 1000000000; divisor > 0; divisor /= 10) + { + quotient = n / divisor; + char digit = (char) (sign * (quotient % 10) + '0'); + if(digit != '0' || showZeros) + { + operator<<(digit); + showZeros = true; + } + } + return *this; +} + +qkernel::TTY& qkernel::TTY::operator<<(char c) +{ + switch(c) + { + case '\n': + cursor = (cursor + 160) - (cursor % 160); + break; + case '\t': + cursor = (cursor + 8) - (cursor % 8); + break; + case '\r': + cursor -= cursor % 160; + break; + default: + vga[cursor * 2] = c; + } + cursor++; + return *this; +} + +void qkernel::TTY::clear() +{ + for(int i = 0; i < 80*25; i++) + { + vga[i * 2] = ' '; + } + cursor = 0; +} + +qkernel::TTY& qkernel::TTY::printNumber(unsigned int n, int base = 10, bool sign = true, bool leadingZeros = false) +{ + if(n == 0) + { + operator<<('0'); + return *this; + } + + if(sign) + { + int nSig = (int) n; + int sign = nSig > 0 ? 1 : -1; + if(sign == -1) + { + n = (unsigned int) (nSig * sign); + operator<<('-'); + } + } + + int initDivisor = (base == 10) ? 1000000000 : + ((base == 16) ? 0x10000000 : + ((base == 8) ? 0x40000000 : 0)); + + int quotient; + bool showZeros = leadingZeros; + for(int divisor = 1000000000; divisor > 0; divisor /= base) + { + quotient = n / divisor; + char digit = (char) (sign * (quotient % base) + '0'); + if(digit != '0' || showZeros) + { + operator<<(digit); + showZeros = true; + } + } + return *this; +} diff --git a/src/tty.h b/src/tty.h new file mode 100644 index 0000000..43dddbf --- /dev/null +++ b/src/tty.h @@ -0,0 +1,35 @@ +#ifndef TTY_H_ +#define TTY_H_ + +namespace qkernel +{ + +class TTY +{ +public: + + + TTY(char* vga); + + TTY& operator<<(const char* str); + + TTY& operator<<(int n); + + TTY& operator<<(char c); + + void clear(); + +private: + + TTY& printNumber(unsigned int n, int base, bool sign, + bool leadingZeros); + + char* vga; + + int cursor; + +}; + +} + +#endif From 52c3754305ad05a2e82d113ab5dfdfd334710e0c Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 9 Jul 2020 18:50:13 -0500 Subject: [PATCH 03/10] Simple physical memory allocator, virtual memory manager --- .gitignore | 3 +- Makefile | 6 +- src/addressspace.cpp | 34 +++- src/{addressspace.h => addressspace.hpp} | 12 +- src/buddyallocator.cpp | 80 +++++--- src/{buddyallocator.h => buddyallocator.hpp} | 46 ++--- src/entry.S | 124 +++++++++++-- src/interruptdescriptor.cpp | 41 +++++ src/interruptdescriptor.hpp | 52 ++++++ src/inthandlers.cpp | 17 ++ src/inthandlers.hpp | 12 ++ src/linker.ld | 2 +- ...{memoryallocator.h => memoryallocator.hpp} | 23 +-- src/memorymap.cpp | 38 ++++ src/memorymap.hpp | 61 ++++++ src/multiboot2header.S | 2 +- src/pagetableentry.cpp | 146 ++++++++------- src/pagetableentry.h | 56 ------ src/pagetableentry.hpp | 58 ++++++ src/quarkkernel.cpp | 33 +++- src/systeminfo.cpp | 16 ++ src/systeminfo.hpp | 33 ++++ src/systypes.hpp | 9 + src/tty.cpp | 174 +++++++++--------- src/tty.h | 33 +++- 25 files changed, 795 insertions(+), 316 deletions(-) rename src/{addressspace.h => addressspace.hpp} (65%) rename src/{buddyallocator.h => buddyallocator.hpp} (60%) create mode 100644 src/interruptdescriptor.cpp create mode 100644 src/interruptdescriptor.hpp create mode 100644 src/inthandlers.cpp create mode 100644 src/inthandlers.hpp rename src/{memoryallocator.h => memoryallocator.hpp} (63%) create mode 100644 src/memorymap.cpp create mode 100644 src/memorymap.hpp delete mode 100755 src/pagetableentry.h create mode 100755 src/pagetableentry.hpp create mode 100644 src/systeminfo.cpp create mode 100644 src/systeminfo.hpp create mode 100644 src/systypes.hpp diff --git a/.gitignore b/.gitignore index d0b6b8e..63e9dc8 100755 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ src/*.o quark.iso src/*~ *~ -rootfs \ No newline at end of file +rootfs +test/ \ No newline at end of file diff --git a/Makefile b/Makefile index 77f81a1..e04ac77 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ src/cstring.o src/error.o src/pagetableentry.o src/multiboot2header.o\ - src/entry.o src/quarkkernel.o + src/systeminfo.o src/memorymap.o src/entry.o src/quarkkernel.o link_script = src/linker.ld quark_bin = qkernel quark_img = quark.iso @@ -13,11 +13,11 @@ CPPFLAGS = -ffreestanding -O2 -Wall -fno-exceptions -fno-rtti -ggdb .PHONY: all all: $(quark_img) -$(quark_img): bin/$(quark_bin) +$(quark_img): bin/$(quark_bin) rootfs/boot/grub/grub.cfg cp bin/$(quark_bin) rootfs/apps grub-mkrescue -o $@ rootfs -bin/$(quark_bin): $(objs) +bin/$(quark_bin): $(objs) $(link_script) mkdir -p bin/ $(CXX) -o $@ -T $(link_script) -ffreestanding -nostdlib -O0 $^ -lgcc diff --git a/src/addressspace.cpp b/src/addressspace.cpp index a62b903..d8663c8 100644 --- a/src/addressspace.cpp +++ b/src/addressspace.cpp @@ -1,14 +1,37 @@ -#include "addressspace.h" +#include "addressspace.hpp" qkernel::AddressSpace::AddressSpace(MemoryAllocator& malloc) : malloc(malloc) { this->pageTables = (PageTableEntry*) 0xFFC00000; + this->pageDirectory = (PageTableEntry*) 0xFFFFF000; } void* qkernel::AddressSpace::mmap(void* start, size_t length) { - + 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 = malloc.allocate(4096); + pageDirectory[directoryIndex] = newPT; + pageDirectory[directoryIndex].setPresent(true); + pageDirectory[directoryIndex].setUsermode(false); + pageDirectory[directoryIndex].setRw(true); + } + if(!pageTables[tableIndex].getPresent()) + { + physaddr_t page = malloc.allocate(4096); + pageTables[tableIndex] = page; + pageTables[tableIndex].setUsermode(false); + pageTables[tableIndex].setRw(true); + pageTables[tableIndex].setPresent(true); + } + tableIndex++; + } + return start; } void qkernel::AddressSpace::munmap(void* start, size_t length) @@ -16,12 +39,13 @@ void qkernel::AddressSpace::munmap(void* start, size_t length) } -void* qkernel::AddressSpace::getPhysicalAddress(void* virtualAddress) const +physaddr_t qkernel::AddressSpace::getPhysicalAddress(void* virtualAddress) + const { size_t index = (size_t) virtualAddress / 4096; PageTableEntry pte = pageTables[index]; if(pte.getPresent()) - return (void*) pte.getPhysicalAddress(); + return pte.getPhysicalAddress(); else - return (void*) 0; + return 0; } diff --git a/src/addressspace.h b/src/addressspace.hpp similarity index 65% rename from src/addressspace.h rename to src/addressspace.hpp index 276a6c7..de5c63e 100755 --- a/src/addressspace.h +++ b/src/addressspace.hpp @@ -3,8 +3,9 @@ #include -#include "memoryallocator.h" -#include "pagetableentry.h" +#include "memoryallocator.hpp" +#include "pagetableentry.hpp" +#include "systypes.hpp" namespace qkernel { @@ -17,7 +18,7 @@ public: void munmap(void* start, size_t length); - void* getPhysicalAddress(void* virtualAddress) const; + physaddr_t getPhysicalAddress(void* virtualAddress) const; private: @@ -29,6 +30,11 @@ private: */ PageTableEntry* pageTables; + /** + * Array of 1024 PDEs, located at the end of the pageTables array + */ + PageTableEntry* pageDirectory; + }; } /* namespace qkernel */ diff --git a/src/buddyallocator.cpp b/src/buddyallocator.cpp index a2462b0..fb8a60a 100755 --- a/src/buddyallocator.cpp +++ b/src/buddyallocator.cpp @@ -1,5 +1,7 @@ -#include "buddyallocator.h" +#include "buddyallocator.hpp" #include "math.h" +#include "systypes.hpp" +#include "memorymap.hpp" #define roundUp(n, m) ((n % m == 0) ? n : (n + m - (n % m))) @@ -8,9 +10,41 @@ qkernel::BuddyAllocator::BuddyAllocator() } -qkernel::BuddyAllocator::BuddyAllocator(void* heapLocation, char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight) +qkernel::BuddyAllocator::BuddyAllocator(qkernel::MemoryMap& memmap, + char* bitmap, size_t blockCount, + size_t treeHeight) +{ + this->bitmap = bitmap; + this->blockSize = 4096; + this->blockCount = blockCount; + this->treeHeight = treeHeight; + for(size_t i = 0; i <= treeHeight; i++) + { + for(size_t j = 0; j < (blockCount >> i); j++) + { + reserveNode(i, j); + } + } + physaddr_t location = 0x100000; + for(size_t i = 0; i < memmap.size() && memmap[i].getSize() > 0; i++) + { + if(memmap[i].getType() != qkernel::MemoryMap::AVAILABLE) + continue; + if(memmap[i].getLocation() > location) + location = roundUp(memmap[i].getLocation(), 4096); + while(memmap[i].contains(location, 4096)) + { + freeNode(0, location / 4096); + if(isFree(0, getBuddy(location / 4096))) + merge(0, location / 4096); + location += 4096; + } + } +} + +qkernel::BuddyAllocator::BuddyAllocator(char* bitmap, size_t blockSize, + size_t blockCount, size_t treeHeight) { - this->heapLocation = heapLocation; this->bitmap = bitmap; this->blockSize = blockSize; this->blockCount = blockCount; @@ -27,7 +61,7 @@ qkernel::BuddyAllocator::BuddyAllocator(void* heapLocation, char* bitmap, size_t } } -void* qkernel::BuddyAllocator::allocate(size_t size) +physaddr_t qkernel::BuddyAllocator::allocate(size_t size) { size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); if(height > treeHeight) // Requested block size is greater than maximum @@ -49,7 +83,7 @@ void* qkernel::BuddyAllocator::allocate(size_t size) } } -void qkernel::BuddyAllocator::free(void* location, size_t size) +void qkernel::BuddyAllocator::free(physaddr_t location, size_t size) { size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); if(height <= treeHeight) @@ -66,7 +100,7 @@ void qkernel::BuddyAllocator::free(void* location, size_t size) size_t qkernel::BuddyAllocator::freeBlocks() const { size_t count = 0; - for(int j = 0; j < blockCount; j++) + for(size_t j = 0; j < blockCount; j++) { if(isFree(0, j)) { @@ -78,9 +112,9 @@ size_t qkernel::BuddyAllocator::freeBlocks() const size_t qkernel::BuddyAllocator::maxAllocationSize() const { - for(int i = treeHeight; i >= 0; i--) + for(size_t i = treeHeight; i >= 0; i--) { - for(int j = 0; j < (blockCount >> i); j++) + for(size_t j = 0; j < (blockCount >> i); j++) { if(isFree(i, j)) { @@ -96,19 +130,14 @@ size_t qkernel::BuddyAllocator::getBlockSize() const return blockSize; } -size_t qkernel::BuddyAllocator::getHeapSize() const +size_t qkernel::BuddyAllocator::getMemorySize() const { return blockCount; } -void* qkernel::BuddyAllocator::getHeapLocation() const -{ - return heapLocation; -} - size_t qkernel::BuddyAllocator::findFreeBlock(size_t height) { - for(int i = 0; i < (blockCount >> height); i++) + for(size_t i = 0; i < (blockCount >> height); i++) { if(isFree(height, i)) { @@ -179,35 +208,38 @@ size_t qkernel::BuddyAllocator::getChild(size_t index) return index * 2; } -void* qkernel::BuddyAllocator::nodeToAddress(size_t height, size_t index) const +physaddr_t qkernel::BuddyAllocator::nodeToAddress(size_t height, size_t index) + const { - char* base = (char*) heapLocation; - return reinterpret_cast(base + index * (blockSize << height)); + return index * (blockSize << height); } -size_t qkernel::BuddyAllocator::addressToNode(size_t height, void* location) const +size_t qkernel::BuddyAllocator::addressToNode(size_t height, + physaddr_t location) const { - size_t offset = (char*) location - (char*) heapLocation; - return offset / (blockSize << height); + return location / (blockSize << height); } void qkernel::BuddyAllocator::reserveNode(size_t height, size_t index) { - size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + size_t bit = (height == 0) ? 0 + : ((blockCount * 2) - (blockCount >> (height - 1))); bit += index; bitmap[bit / 8] |= 1 << (bit % 8); } void qkernel::BuddyAllocator::freeNode(size_t height, size_t index) { - size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + size_t bit = (height == 0) ? 0 + : ((blockCount * 2) - (blockCount >> (height - 1))); bit += index; bitmap[bit / 8] &= ~(1 << (bit % 8)); } bool qkernel::BuddyAllocator::isFree(size_t height, size_t index) const { - size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + size_t bit = (height == 0) ? 0 + : ((blockCount * 2) - (blockCount >> (height - 1))); bit += index; char data = bitmap[bit / 8] & (1 << (bit % 8)); if(data == 0) diff --git a/src/buddyallocator.h b/src/buddyallocator.hpp similarity index 60% rename from src/buddyallocator.h rename to src/buddyallocator.hpp index f14b7a8..2be4b14 100755 --- a/src/buddyallocator.h +++ b/src/buddyallocator.hpp @@ -1,7 +1,8 @@ #ifndef BUDDYALLOCATOR_H_ #define BUDDYALLOCATOR_H_ -#include "memoryallocator.h" +#include "memoryallocator.hpp" +#include "memorymap.hpp" namespace qkernel { @@ -12,18 +13,23 @@ public: BuddyAllocator(); - BuddyAllocator(void* heapLocation, char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight); + BuddyAllocator(MemoryMap& memmap, char* bitmap, size_t blockCount, + size_t treeHeight); + + BuddyAllocator(char* bitmap, size_t blockSize, size_t blockCount, + size_t treeHeight); + + /** + * Allocate a block of memory containing at least 'size' bytes. + * Rounds up to the nearest power of 2 times the size of a block. + */ + virtual physaddr_t allocate(size_t size); /** - * Allocate a block of memory containing at least 'size' bytes. Rounds up to the nearest - * power of 2 times the size of a block. + * Free the region of memory starting at 'location' and containing + * 'size' bytes. */ - virtual void* allocate(size_t size); - - /** - * Free the region of memory starting at 'location' and containing 'size' bytes. - */ - virtual void free(void* location, size_t size); + virtual void free(physaddr_t location, size_t size); /** * @returns the total number of free blocks of memory. @@ -31,8 +37,8 @@ public: virtual size_t freeBlocks() const; /** - * @returns the size in blocks of the largest possible allocation that will not - * fail due to lack of memory. + * @returns the size in blocks of the largest possible allocation that + * will not fail due to lack of memory. */ virtual size_t maxAllocationSize() const; @@ -42,21 +48,15 @@ public: virtual size_t getBlockSize() const; /** - * @returns the total number of blocks managed by this memory allocator. + * @returns the total number of blocks managed by this memory + * allocator. */ - virtual size_t getHeapSize() const; - - /** - * @returns a pointer to the beginning of the heap managed by this memory allocator. - */ - virtual void* getHeapLocation() const; + virtual size_t getMemorySize() const; private: static const size_t INVALID = (size_t) -1; - void* heapLocation; - char* bitmap; size_t blockSize; @@ -77,9 +77,9 @@ private: size_t getChild(size_t index); - void* nodeToAddress(size_t height, size_t index) const; + physaddr_t nodeToAddress(size_t height, size_t index) const; - size_t addressToNode(size_t height, void* location) const; + size_t addressToNode(size_t height, physaddr_t location) const; void reserveNode(size_t height, size_t index); diff --git a/src/entry.S b/src/entry.S index 5e8ccf8..92768e1 100755 --- a/src/entry.S +++ b/src/entry.S @@ -1,6 +1,12 @@ .section .multiboot .include "src/multiboot2header.S" +.section .rodata + +idt_info: +.short idt_end - idt - 1 +.long idt + .section .bss .align 16 @@ -16,6 +22,24 @@ _tempIdentityMap: _tempPgTable: .skip 8192 +_bootCmdLine: +.skip 64 + +.align 64 +.global system_info +system_info: +.skip 16 + +.align 64 +.global memory_map +memory_map: +.skip 16 * 16 + +.global idt +idt: +.skip 8 * 256 +idt_end: + .section .text .global _start .type _start, @function @@ -25,13 +49,85 @@ _start: movb $64, 0xB8000 + mov $system_info, %edi + sub $BASE_DIFF, %edi + add $8, %ebx + +switch: mov (%ebx), %eax + cmp $0, %eax + je s_end + cmp $1, %eax + je tag_1 + cmp $4, %eax + je tag_4 + cmp $6, %eax + je tag_6 + cmp $21, %eax + je tag_21 + jmp def + +# Boot command line +tag_1: mov 4(%ebx), %ecx + sub $8, %ecx + mov %ebx, %esi + add $8, %esi + mov $_bootCmdLine, %edi + sub $BASE_DIFF, %edi + rep movsb + mov $system_info, %edi + sub $BASE_DIFF, %edi + jmp def + +# Basic memory info +tag_4: mov 8(%ebx), %eax + mov %eax, (%edi) + mov 12(%ebx), %eax + mov %eax, 4(%edi) + jmp def + +# Memory map +tag_6: mov $memory_map, %esi + sub $BASE_DIFF, %esi # set esi to point to the table in the kernel image + mov 4(%ebx), %ecx + sub $16, %ecx # set ecx to store the size of the table provided by the bootloader + mov 8(%ebx), %edx # set edx to store the size of each table entry + add $16, %ebx # move ebx up to the first entry +1: mov (%ebx), %eax + mov %eax, (%esi) # save the address of that region in memory + mov 8(%ebx), %eax + mov %eax, 4(%esi) # save the size of that region in memory + mov 16(%ebx), %eax + mov %eax, 8(%esi) # save the type of memory in that region + add $12, %esi # move esi to the next entry in the kernel's array + add %edx, %ebx # move ebx to the next entry in the bootloader's array + sub %edx, %ecx # subtract the size of an entry from ecx. + jnz 1b # loop if there are entries left + mov $0, %eax + mov %eax, (%esi) + mov %eax, 4(%esi) + mov %eax, 8(%esi) + jmp switch + +# Program image location +tag_21: mov 8(%ebx), %eax + mov %eax, 8(%edi) + jmp def + +def: mov 4(%ebx), %eax + add $7, %eax + and $0xFFFFFFF8, %eax + add %eax, %ebx + jmp switch +s_end: + + movb $64, 0xB8002 + mov $0, %ecx 1: # Generate a page table entry pointing to a page in the kernel binary mov %ecx, %eax mov $4096, %edx mul %edx - add $PHYSICAL_BASE, %eax or $3, %eax # Load the address of the temporary page table and translate it to a physical address @@ -46,11 +142,13 @@ _start: sub $BASE_DIFF, %edi # Save the PTE into an entry in the identity map - mov %eax, 1024(%edi, %ecx, 4) + mov %eax, (%edi, %ecx, 4) # Increment count and loop inc %ecx - cmp $IMAGE_SIZE, %ecx + mov $IMAGE_SIZE, %edx + add $256, %edx + cmp %edx, %ecx jne 1b # Load the physical address of the identity map, and generate a PDE @@ -72,20 +170,11 @@ _start: # Save the PDE to the entry corresponding to 0xC0000000 mov %eax, 3072(%edi) - - # Add another PDE for extra mappings the kernel needs - add $4096, %eax - mov %eax, 3076(%edi) # Set the last entry in the page directory to point to the page directory itself - or $3, %edi - mov %edi, 4092(%edi) - - # Map VGA memory into the address space - mov $_tempPgTable, %edi - sub $BASE_DIFF, %edi - mov $0xB8003, %eax - mov %eax, 4096(%edi) + mov %edi, %eax + or $3, %eax + mov %eax, 4092(%edi) # Load the physical address of the page directory into CR3 mov $_tempPgDir, %edi @@ -111,7 +200,10 @@ _start: # Initialize stack mov $stackTop, %esp - push %ebx + lidt idt_info + + mov $_bootCmdLine, %eax + push %eax # Call main function call main diff --git a/src/interruptdescriptor.cpp b/src/interruptdescriptor.cpp new file mode 100644 index 0000000..cbbdf79 --- /dev/null +++ b/src/interruptdescriptor.cpp @@ -0,0 +1,41 @@ +#include "interruptdescriptor.hpp" + +qkernel::InterruptDescriptor::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; +} + +qkernel::InterruptDescriptor::InterruptDescriptor(void* handler, + Type type, unsigned int dpl) +{ + uint32_t offset = (uint32_t) handler; + this->m_offset1 = (uint16_t) offset; + this->m_selector = 1; + this->m_zero = 0; + this->m_type = (uint16_t) type; + this->m_storage = 0; + this->m_dpl = dpl; + this->m_present = 0; + this->m_offset = (uint16_t) (offset >> 16); +} + +bool qkernel::InterruptDescriptor::present() +{ + return m_present == 1; +} +void qkernel::InterruptDescriptor::present(bool present) +{ + m_present = present ? 1 : 0; +} + +Type qkernel::InterruptDescriptor::type() +{ + +} diff --git a/src/interruptdescriptor.hpp b/src/interruptdescriptor.hpp new file mode 100644 index 0000000..31edfce --- /dev/null +++ b/src/interruptdescriptor.hpp @@ -0,0 +1,52 @@ +#ifndef INTERRUPTDESCRIPTOR_H +#define INTERRUPTDESCRIPTOR_H + +#include + +namespace qkernel +{ + +class InterruptDescriptor +{ +public: + + enum Type + { + TASK32 = 5, + TRAP32 = 15, + INT32 = 14, + TRAP16 = 7, + INT16 = 6 + }; + + InterruptDescriptor(); + + InterruptDescriptor(void* handler, unsigned int type, unsigned int dpl); + + bool present(); + + void present(bool present); + + Type type(); + + void type(Type type); + + + void* operator=(void* 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; + +}; + +} + +#endif diff --git a/src/inthandlers.cpp b/src/inthandlers.cpp new file mode 100644 index 0000000..f5330b2 --- /dev/null +++ b/src/inthandlers.cpp @@ -0,0 +1,17 @@ +#include "inthandlers.hpp" + +extern "C" +__attribute__ ((interrupt)) +void gpFaultHandler(void* frame, unsigned int error) +{ + +} + +extern "C" +__attribute__ ((interrupt)) +void pageFaultHandler(unsigned int error) +{ + +} + +} diff --git a/src/inthandlers.hpp b/src/inthandlers.hpp new file mode 100644 index 0000000..405ad56 --- /dev/null +++ b/src/inthandlers.hpp @@ -0,0 +1,12 @@ +#ifndef INTHANDLERS_H +#define INTHANDLERS_H + +extern "C" +__attribute__ ((interrupt)) +void gpFaultHandler(void* frame, unsigned int error); + +extern "C" +__attribute__ ((interrupt)) +void pageFaultHandler(void* frame, unsigned int error); + +#endif diff --git a/src/linker.ld b/src/linker.ld index 713d4d7..36695c7 100755 --- a/src/linker.ld +++ b/src/linker.ld @@ -2,7 +2,7 @@ ENTRY(_start) SECTIONS { - . = 0xC0000000; + . = 0xC0100000; VIRTUAL_BASE = .; PHYSICAL_BASE = 0x100000; BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; diff --git a/src/memoryallocator.h b/src/memoryallocator.hpp similarity index 63% rename from src/memoryallocator.h rename to src/memoryallocator.hpp index d420849..b14c8a3 100755 --- a/src/memoryallocator.h +++ b/src/memoryallocator.hpp @@ -2,6 +2,7 @@ #define __MEMORYALLOCATOR_H_ #include +#include "systypes.hpp" namespace qkernel { @@ -17,12 +18,13 @@ public: * Allocate a block of memory containing 'size' bytes. May round up * depending on the implementation. */ - virtual void* allocate(size_t size) = 0; + virtual physaddr_t allocate(size_t size) = 0; /** - * Free the region of memory starting at 'location' and containing 'size' bytes. + * Free the region of memory starting at 'location' and containing + * 'size' bytes. */ - virtual void free(void* location, size_t size) = 0; + virtual void free(physaddr_t location, size_t size) = 0; /** * @returns the total number of free blocks of memory. @@ -30,8 +32,8 @@ public: virtual size_t freeBlocks() const = 0; /** - * @returns the size in blocks of the largest possible allocation that will not - * fail due to lack of memory. + * @returns the size in blocks of the largest possible allocation that + * will not fail due to lack of memory. */ virtual size_t maxAllocationSize() const = 0; @@ -41,15 +43,10 @@ public: virtual size_t getBlockSize() const = 0; /** - * @returns the total number of blocks managed by this memory allocator. + * @returns the total number of blocks managed by this memory + * allocator. */ - virtual size_t getHeapSize() const = 0; - - /** - * @returns a pointer to the beginning of the heap managed by this memory allocator. - */ - virtual void* getHeapLocation() const = 0; - + virtual size_t getMemorySize() const = 0; }; diff --git a/src/memorymap.cpp b/src/memorymap.cpp new file mode 100644 index 0000000..96a5fab --- /dev/null +++ b/src/memorymap.cpp @@ -0,0 +1,38 @@ +#include "memorymap.hpp" + +qkernel::MemoryMap::MemoryMap(qkernel::MemoryMap::Region* map, size_t entries) +{ + this->map = map; + this->entries = entries; +} + +qkernel::MemoryMap::Region& qkernel::MemoryMap::operator[](size_t index) +{ + return map[index]; +} + +size_t qkernel::MemoryMap::size() +{ + return entries; +} + +physaddr_t qkernel::MemoryMap::Region::getLocation() +{ + return location; +} + +size_t qkernel::MemoryMap::Region::getSize() +{ + return size; +} + +qkernel::MemoryMap::Type qkernel::MemoryMap::Region::getType() +{ + return (Type) type; +} + +bool qkernel::MemoryMap::Region::contains(physaddr_t location, size_t size) +{ + return (location >= this->location) && + (location + size <= this->location + this->size); +} diff --git a/src/memorymap.hpp b/src/memorymap.hpp new file mode 100644 index 0000000..6a762a7 --- /dev/null +++ b/src/memorymap.hpp @@ -0,0 +1,61 @@ +#ifndef MEMORYMAP_H +#define MEMORYMAP_H + +#include +#include + +#include "systypes.hpp" + +namespace qkernel +{ + +class MemoryMap +{ +public: + + enum Type + { + AVAILABLE = 1, + ACPI = 3, + DEFECTIVE = 5 + }; + + class Region + { + public: + + physaddr_t getLocation(); + + size_t getSize(); + + Type getType(); + + bool contains(physaddr_t location, size_t size); + + private: + + physaddr_t location; + + size_t size; + + uint32_t type; + + }; + + MemoryMap(Region* map, size_t entries); + + Region& operator[](size_t index); + + size_t size(); + +private: + + Region* map; + + size_t entries; + +}; + +} + +#endif diff --git a/src/multiboot2header.S b/src/multiboot2header.S index 8f6f476..44bc2f3 100755 --- a/src/multiboot2header.S +++ b/src/multiboot2header.S @@ -28,7 +28,7 @@ .set tagEntryType, 3 .set tagEntrySize, 12 -.set tagEntryAddress, _start - (0xC0000000 - 0x100000) +.set tagEntryAddress, _start - (0xC0100000 - 0x100000) .set tagModuleAlignType, 6 .set tagModuleAlignSize, 8 diff --git a/src/pagetableentry.cpp b/src/pagetableentry.cpp index 97ceb31..66af515 100755 --- a/src/pagetableentry.cpp +++ b/src/pagetableentry.cpp @@ -5,7 +5,7 @@ * Author: nathan */ -#include "pagetableentry.h" +#include "pagetableentry.hpp" namespace qkernel { @@ -26,102 +26,108 @@ PageTableEntry::PageTableEntry() { this->physicalAddress = 0; } -uint32_t PageTableEntry::getAccessed() const { - return accessed; +bool PageTableEntry::getAccessed() const { + return accessed == 1; } -uint32_t PageTableEntry::getCacheDisable() const { - return cacheDisable; -} - -void PageTableEntry::setCacheDisable(uint32_t cacheDisable) +bool PageTableEntry::getCacheDisable() const { - this->cacheDisable = cacheDisable; + return cacheDisable == 1; } -uint32_t PageTableEntry::getDirty() const { - return dirty; -} - -uint32_t PageTableEntry::getGlobal() const { - return global; -} - -void PageTableEntry::setGlobal(uint32_t global) +void PageTableEntry::setCacheDisable(bool cacheDisable) { - this->global = global; + this->cacheDisable = cacheDisable ? 1 : 0; } -uint32_t PageTableEntry::getPat() const { - return pat; -} - -void PageTableEntry::setPat(uint32_t pat) +bool PageTableEntry::getDirty() const { - this->pat = pat; + return dirty == 1; } -uint32_t PageTableEntry::getPhysicalAddress() const { - uint32_t physicalAddress = this->physicalAddress; +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; } -uint32_t PageTableEntry::setPhysicalAddress(uint32_t physicalAddress) +physaddr_t PageTableEntry::setPhysicalAddress(physaddr_t physicalAddress) { - if(physicalAddress % 4096 == 0) - { - this->physicalAddress = physicalAddress >> 12; - return this->physicalAddress; - } - else - { - this->physicalAddress = !physicalAddress; - return this->physicalAddress; - } + this->physicalAddress = physicalAddress >> 12; + return this->physicalAddress << 12; } -uint32_t PageTableEntry::getPresent() const { - return present; -} - -void PageTableEntry::setPresent(uint32_t present) +bool PageTableEntry::getPresent() const { - this->present = present; + return present == 1; } -uint32_t PageTableEntry::getRw() const { - return rw; -} - -void PageTableEntry::setRw(uint32_t rw) +void PageTableEntry::setPresent(bool present) { - this->rw = rw; + this->present = present ? 1 : 0; } -uint32_t PageTableEntry::getUsermode() const { - return usermode; -} - -void PageTableEntry::setUsermode(uint32_t usermode) +bool PageTableEntry::getRw() const { - this->usermode = usermode; + return rw == 1; } -uint32_t PageTableEntry::getWriteThrough() const { - return writeThrough; -} - -uint32_t PageTableEntry::getShared() const { - return shared; -} - -void PageTableEntry::setShared(uint32_t shared) { - this->shared = shared; -} - -void PageTableEntry::setWriteThrough(uint32_t writeThrough) +void PageTableEntry::setRw(bool rw) { - this->writeThrough = writeThrough; + this->rw = rw ? 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; +} + +bool PageTableEntry::getShared() const +{ + return shared == 1; +} + +void PageTableEntry::setShared(bool shared) +{ + this->shared = shared ? 1 : 0; +} + +void PageTableEntry::setWriteThrough(bool writeThrough) +{ + this->writeThrough = writeThrough ? 1 : 0; +} + +physaddr_t PageTableEntry::operator=(physaddr_t rhs) +{ + return setPhysicalAddress(rhs); } } /* namespace qkernel */ diff --git a/src/pagetableentry.h b/src/pagetableentry.h deleted file mode 100755 index 021b942..0000000 --- a/src/pagetableentry.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * PageTableEntry.h - * - * Created on: May 22, 2019 - * Author: nathan - */ - -#ifndef SRC_PAGETABLEENTRY_H_ -#define SRC_PAGETABLEENTRY_H_ - -#include - -namespace qkernel { - -class PageTableEntry { -public: - PageTableEntry(); - uint32_t getAccessed() const; - uint32_t getCacheDisable() const; - void setCacheDisable(uint32_t cacheDisable); - uint32_t getDirty() const; - uint32_t getGlobal() const; - void setGlobal(uint32_t global); - uint32_t getPat() const; - void setPat(uint32_t pat); - uint32_t getPhysicalAddress() const; - uint32_t setPhysicalAddress(uint32_t physicalAddress); - uint32_t getPresent() const; - void setPresent(uint32_t present); - uint32_t getRw() const; - void setRw(uint32_t rw); - uint32_t getShared() const; - void setShared(uint32_t shared); - uint32_t getUsermode() const; - void setUsermode(uint32_t usermode); - uint32_t getWriteThrough() const; - void setWriteThrough(uint32_t writeThrough); - -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; -}; - -} /* namespace qkernel */ - -#endif /* SRC_PAGETABLEENTRY_H_ */ diff --git a/src/pagetableentry.hpp b/src/pagetableentry.hpp new file mode 100755 index 0000000..7e7a3f4 --- /dev/null +++ b/src/pagetableentry.hpp @@ -0,0 +1,58 @@ +/* + * PageTableEntry.h + * + * Created on: May 22, 2019 + * Author: nathan + */ + +#ifndef SRC_PAGETABLEENTRY_H_ +#define SRC_PAGETABLEENTRY_H_ + +#include +#include "systypes.hpp" + +namespace qkernel { + +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); + +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; +}; + +} /* namespace qkernel */ + +#endif /* SRC_PAGETABLEENTRY_H_ */ diff --git a/src/quarkkernel.cpp b/src/quarkkernel.cpp index 9f9cdbc..e9db5f5 100755 --- a/src/quarkkernel.cpp +++ b/src/quarkkernel.cpp @@ -1,24 +1,39 @@ #include #include +#include "systypes.hpp" +#include "systeminfo.hpp" +#include "memorymap.hpp" +#include "buddyallocator.hpp" +#include "addressspace.hpp" #include "tty.h" #if __STDC_HOSTED__ == 1 || __i686__ != 1 #error "ERROR: This program must be compiled for a freestanding environment, and currently only supports the i686 target." #endif -#include "buddyallocator.h" - using namespace qkernel; -void main(void* bootInfo) +extern SystemInfo system_info; +extern MemoryMap::Region memory_map; + +void main(char* cmdline) { - char* vga = (char*) 0xC0400000; - TTY tty(vga); + TTY tty((char*) 0xC00B8000); tty << "--Quark Kernel--\n"; - tty << "Successfully enabled paging. Kernel image mapped to 0xC0000000.\n"; + tty << "Low memory: \t" << (int) system_info.getLowMemory() << " KiB\n"; + tty << "High memory:\t" << (int) system_info.getHighMemory() << " KiB\n"; + tty << "Type\t\tLocation\t\tSize\n"; + MemoryMap memmap(&memory_map, 16); + for(size_t i = 0; i < memmap.size() && memmap[i].getSize() > 0; i++) + { + tty << (int) memmap[i].getType() << "\t\t\t" + << (void*) memmap[i].getLocation() << "\t\t" + << (int) memmap[i].getSize() << "\n"; + } + BuddyAllocator alloc(memmap, (char*) 0xC0000000, + system_info.getHighMemory() / 4 + 256, 6); + AddressSpace vmem(alloc); + tty << vmem.mmap((void*) 0x80000000, 0x10000) << '\n'; tty << "Nothing left to do. Hanging.\n"; - tty << 18542; - char c = 'b'; - return; } diff --git a/src/systeminfo.cpp b/src/systeminfo.cpp new file mode 100644 index 0000000..889e314 --- /dev/null +++ b/src/systeminfo.cpp @@ -0,0 +1,16 @@ +#include "systeminfo.hpp" + +size_t qkernel::SystemInfo::getLowMemory() +{ + return lowMemory; +} + +size_t qkernel::SystemInfo::getHighMemory() +{ + return highMemory; +} + +physaddr_t qkernel::SystemInfo::getKernelBase() +{ + return kernelBase; +} diff --git a/src/systeminfo.hpp b/src/systeminfo.hpp new file mode 100644 index 0000000..6aedfde --- /dev/null +++ b/src/systeminfo.hpp @@ -0,0 +1,33 @@ +#ifndef SYSTEMINFO_H +#define SYSTEMINFO_H + +#include + +#include "systypes.hpp" + +namespace qkernel +{ + +class SystemInfo +{ +public: + + size_t getLowMemory(); + + size_t getHighMemory(); + + physaddr_t getKernelBase(); + +private: + + size_t lowMemory; + + size_t highMemory; + + physaddr_t kernelBase; + +}; + +} + +#endif diff --git a/src/systypes.hpp b/src/systypes.hpp new file mode 100644 index 0000000..cf07e96 --- /dev/null +++ b/src/systypes.hpp @@ -0,0 +1,9 @@ +#ifndef SYSTYPES_H +#define SYSTYPES_H + +#include +#include + +typedef uint32_t physaddr_t; + +#endif diff --git a/src/tty.cpp b/src/tty.cpp index 191304d..0ae4832 100644 --- a/src/tty.cpp +++ b/src/tty.cpp @@ -5,76 +5,59 @@ qkernel::TTY::TTY(char* vga) { this->vga = vga; this->cursor = 0; + this->width = 0; + this->base = 10; +} + +qkernel::TTY& qkernel::TTY::operator<<(qkernel::TTY::Format fmt) +{ + switch(fmt) + { + case Binary: + base = 2; + break; + case Decimal: + base = 10; + break; + case Hex: + base = 16; + break; + } } qkernel::TTY& qkernel::TTY::operator<<(const char* str) { - while(*str) - { - switch(*str) - { - 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] = *str; - cursor++; - } - str++; - } - return *this; + return printString(str); +} + +qkernel::TTY& qkernel::TTY::operator<<(unsigned int n) +{ + return printNumber(n, base, width); } qkernel::TTY& qkernel::TTY::operator<<(int n) { - if(n == 0) - { - operator<<('0'); - return *this; - } + return printNumber((unsigned int) n, base, width); +} - int sign = n > 0 ? 1 : -1; - if(sign == -1) operator<<('-'); - - int quotient; - bool showZeros = false; - for(int divisor = 1000000000; divisor > 0; divisor /= 10) - { - quotient = n / divisor; - char digit = (char) (sign * (quotient % 10) + '0'); - if(digit != '0' || showZeros) - { - operator<<(digit); - showZeros = true; - } - } - return *this; +qkernel::TTY& qkernel::TTY::operator<<(void* n) +{ + return printNumber((unsigned int) n, 16, 8); } qkernel::TTY& qkernel::TTY::operator<<(char c) { - switch(c) - { - case '\n': - cursor = (cursor + 160) - (cursor % 160); - break; - case '\t': - cursor = (cursor + 8) - (cursor % 8); - break; - case '\r': - cursor -= cursor % 160; - break; - default: - vga[cursor * 2] = c; - } - cursor++; - return *this; + return putChar(c); +} + +void qkernel::TTY::setWidth(size_t width) +{ + this->width = width; +} + +size_t qkernel::TTY::getWidth() +{ + return width; } void qkernel::TTY::clear() @@ -86,40 +69,57 @@ void qkernel::TTY::clear() cursor = 0; } -qkernel::TTY& qkernel::TTY::printNumber(unsigned int n, int base = 10, bool sign = true, bool leadingZeros = false) +qkernel::TTY& qkernel::TTY::printNumber(unsigned int n, size_t base, + size_t width) { - if(n == 0) + const char* digits = "0123456789ABCDEF"; + char str[33]; + size_t i = 1; + do { - operator<<('0'); - return *this; + str[i] = digits[n % base]; + n /= base; + i++; + } while(n > 0); + while(i <= width) + { + str[i] = '0'; + i++; } - - if(sign) + str[0] = '\0'; + for(char* s = str + (i - 1); *s; s--) { - int nSig = (int) n; - int sign = nSig > 0 ? 1 : -1; - if(sign == -1) - { - n = (unsigned int) (nSig * sign); - operator<<('-'); - } - } - - int initDivisor = (base == 10) ? 1000000000 : - ((base == 16) ? 0x10000000 : - ((base == 8) ? 0x40000000 : 0)); - - int quotient; - bool showZeros = leadingZeros; - for(int divisor = 1000000000; divisor > 0; divisor /= base) - { - quotient = n / divisor; - char digit = (char) (sign * (quotient % base) + '0'); - if(digit != '0' || showZeros) - { - operator<<(digit); - showZeros = true; - } + putChar(*s); + } + return *this; +} + +qkernel::TTY& qkernel::TTY::printString(const char* str) +{ + while(*str) + { + putChar(*str); + str++; + } + return *this; +} + +qkernel::TTY& qkernel::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/tty.h b/src/tty.h index 43dddbf..12327ee 100644 --- a/src/tty.h +++ b/src/tty.h @@ -1,32 +1,57 @@ #ifndef TTY_H_ #define TTY_H_ +#include + namespace qkernel { 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, int base, bool sign, - bool leadingZeros); + 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; }; From 73dd2c8bda7e534fb964be52912ec08212192722 Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Thu, 9 Jul 2020 17:28:41 -0500 Subject: [PATCH 04/10] Deleted some old files --- src/bitmap.h | 609 ------------------------------------------------ src/error.cpp | 33 --- src/error.h | 40 ---- src/errortype.h | 22 -- 4 files changed, 704 deletions(-) delete mode 100755 src/bitmap.h delete mode 100755 src/error.cpp delete mode 100755 src/error.h delete mode 100755 src/errortype.h diff --git a/src/bitmap.h b/src/bitmap.h deleted file mode 100755 index 7e11b7b..0000000 --- a/src/bitmap.h +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Bitmap.h - * - * Created on: Jun 1, 2019 - * Author: nathan - */ - -#ifndef SRC_BITMAP_H_ -#define SRC_BITMAP_H_ - -#include -#include -#include - -namespace qkernel { - -/** - * Represents a fixed array of N bits. Somewhat analogous to std::bitset. Can - * be manipulated using standard arithmetic operators (&, |, ^, ~). - */ -template -class Bitmap { -public: - - /** - * A proxy object used to reference an individual bit contained in a Bitmap object. - */ - class Reference - { - public: - - /** - * Construct a reference to a bit contained in a Bitmap object. - * - * @param data A reference to the byte in which the referenced bit is - * contained - * @param position The position of the referenced bit inside 'data.' 0 - * denotes the least significant bit; 7 denoted the most significant - * bit. - */ - Reference(uint8_t& data, size_t position); - - /** - * Sets the bit referenced by this object to 'b' - * - * @returns a reference to this object - */ - Reference& operator=(const bool b); - - /** - * Sets the bit referenced by this object to the value of the bit - * referenced by 'r.' - * - * @returns a reference to this object - */ - Reference& operator=(const Reference& r); - - /** - * @returns the inverse of the value of the bit referenced by this - * object. - */ - bool operator~() const; - - /** - * Converts the bit referenced by this object to a boolean, whose value - * is 'true' if the bit referenced it set, and false if it is clear. - */ - operator bool() const; - - private: - - uint8_t& data; - - size_t position; - - }; - - /** - * Constructs a bitmap containing 'N' bits, containing uninitialized - * data. - */ - Bitmap(); - - /** - * Constructs a bitmap containing 'N' bits, copying data from 'bitmap' into - * the new object. - */ - Bitmap(const Bitmap& bitmap); - - /** - * Constructs a bitmap containing 'N' bits, initializing each bit to 'v.' - */ - Bitmap(const bool value); - - /** - * Constructs a bitmap containing 'N' bits, initializing the first 32 bits - * to the bits contained in 'value.' If the bitmap contains more than 32 - * bits, the rest are initialized to 0. - */ - Bitmap(const uint8_t value); - - /** - * Constructs a bitmap containing 'N' bits, initializing the first 32 bits - * to the bits contained in 'value.' If the bitmap contains more than 32 - * bits, the rest are initialized to 0. - */ - Bitmap(const uint16_t value); - - /** - * Constructs a bitmap containing 'N' bits, initializing the first 32 bits - * to the bits contained in 'value.' If the bitmap contains more than 32 - * bits, the rest are initialized to 0. - */ - Bitmap(const uint32_t value); - - /** - * @returns the number of bits stored in this bitmap - */ - size_t size(); - - /** - * @returns the number of bits that are set - */ - size_t count(); - - /** - * @returns true if all bits are set; otherwise false. - */ - bool all(); - - /** - * @returns true if at least one bit is set; otherwise false. - */ - bool any(); - - /** - * @returns true if all bits are cleared; otherwise false. - */ - bool none(); - - /** - * Sets all bits in this bitmap. - * - * @returns a reference to this bitmap - */ - Bitmap& set(); - - /** - * Clears all bits in this bitmap. - * - * @returns a reference to this bitmap - */ - Bitmap& clear(); - - /** - * Compares the contents of 'bitmap' and this bitmap. - * - * @param bitmap The bitmap to compare this object to. - * - * @returns true only if each bit in 'other' is equal to each bit in this - * bitmap; otherwise false. - */ - bool operator==(const Bitmap& other) const; - - /** - * Compares the contents of 'bitmap' and this bitmap. - * - * @param bitmap The bitmap to compare this object to. - * - * @returns false only if each bit in 'other' is equal to each bit in this - * bitmap; otherwise true. - */ - bool operator!=(const Bitmap& other) const; - - /** - * Accesses the bit at 'index.' Does not perform bounds checking; - * out-of-bounds access will result in problems. - * - * @param index The position in the bitmap to access - * - * @returns a reference to the bit at 'index' - */ - Reference operator[](const size_t index); - - /** - * Accesses the bit at 'index.' Does not perform bounds checking; - * out-of-bounds access will result in problems. - * - * @param index The position in the bitmap to access - * - * @returns the value of the bit at position 'index' - */ - bool operator[](const size_t index) const; - - /** - * @returns a bitmap containing the bitwise AND of this bitmap and 'other.' - */ - Bitmap operator&(const Bitmap& other) const; - - /** - * Sets the value of this bitmap to the bitwise AND of this bitmap and - * 'other.' - * - * @returns a reference to this bitmap - */ - Bitmap& operator&=(const Bitmap& other); - - /** - * @returns a bitmap containing the bitwise OR of this bitmap and 'other.' - */ - Bitmap operator|(const Bitmap& other) const; - - /** - * Sets the value of this bitmap to the bitwise OR of this bitmap and - * 'other.' - * - * @returns a reference to this bitmap - */ - Bitmap& operator|=(const Bitmap& other); - - /** - * @returns a bitmap containing the bitwise XOR of this bitmap and 'other.' - */ - Bitmap operator^(const Bitmap& other) const; - - /** - * Sets the value of this bitmap to the bitwise OR of this bitmap and - * 'other.' - * - * @returns a reference to this bitmap - */ - Bitmap& operator^=(const Bitmap& other); - - /** - * Shifts this bitmap 'n' bits left. - * - * @returns a new Bitmap containing the result - */ - Bitmap operator<<(const size_t n) const; - - /** - * Shifts this bitmap 'n' bits left. - * - * @returns a reference to this bitmap - */ - Bitmap& operator<<=(const size_t n); - - /** - * Shifts this bitmap 'n' bits right. - * - * @returns a new Bitmap containing the result - */ - Bitmap operator>>(const size_t n) const; - - /** - * Shifts the bitmap 'n' bits right. - * - * @returns a reference to this bitmap - */ - Bitmap& operator>>=(const size_t n); - - /** - * Computes the bitwise NOT of this bitmap - * - * @returns a new bitmap containing the result - */ - Bitmap operator~() const; - -private: - - uint8_t data[(N / 8) + 1]; - -}; - -} /* namespace qkernel */ - -template -inline qkernel::Bitmap::Reference::Reference(uint8_t& data, size_t position) - : data(data) -{ - this->position = position; -} - -template -inline typename qkernel::Bitmap::Reference& qkernel::Bitmap::Reference::operator =(const bool b) { - if(b) - { - data |= 1 << position; - } - else - { - data &= ~(1 << position); - } - return *this; -} - -template -inline typename qkernel::Bitmap::Reference& qkernel::Bitmap::Reference::operator =(const Reference& r) { - if((bool) r) - { - data |= 1 << position; - } - else - { - data &= ~(1 << position); - } -} - -template -inline bool qkernel::Bitmap::Reference::operator ~() const { - return !((bool) (*this)); -} - -template -inline qkernel::Bitmap::Reference::operator bool() const { - uint8_t value = data & (1 << position); - if((data & (1 << position)) != 0) - { - return true; - } - else - { - return false; - } -} - -template -inline qkernel::Bitmap::Bitmap() { -} - -template -inline qkernel::Bitmap::Bitmap(const Bitmap& bitmap) { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = bitmap[i]; - } -} - -template -inline qkernel::Bitmap::Bitmap(const bool value) { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = value; - } -} - -template -inline qkernel::Bitmap::Bitmap(uint8_t value) { - size_t max = N >= 8 ? 8 : N; - for(size_t i = 0; i < max; i++) - { - (*this)[i] = value & 1; - value >>= 1; - } -} - -template -inline qkernel::Bitmap::Bitmap(uint16_t value) { - size_t max = N >= 16 ? 16 : N; - for(size_t i = 0; i < max; i++) - { - (*this)[i] = value & 1; - value >>= 1; - } -} - -template -inline qkernel::Bitmap::Bitmap(uint32_t value) { - size_t max = N >= 32 ? 32 : N; - for(size_t i = 0; i < max; i++) - { - (*this)[i] = value & 1; - value >>= 1; - } -} - -template -inline size_t qkernel::Bitmap::size() { - return N; -} - -template -inline size_t qkernel::Bitmap::count() { - size_t count = 0; - for(size_t i = 0; i < N; i++) - { - if((*this)[i] == true) - { - count++; - } - } - return count; -} - -template -inline bool qkernel::Bitmap::all() { - for(size_t i = 0; i < N; i++) - { - if((*this)[i] == false) - { - return false; - } - } - return true; -} - -template -inline bool qkernel::Bitmap::any() { - for(size_t i = 0; i < N; i++) - { - if((*this)[i] == true) - { - return true; - } - } - return false; -} - -template -inline bool qkernel::Bitmap::none() { - for(size_t i = 0; i < N; i++) - { - if((*this)[i] == true) - { - return false; - } - } - return true; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::set() { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = true; - } - return *this; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::clear() { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = false; - } - return *this; -} - -template -inline bool qkernel::Bitmap::operator ==(const Bitmap& other) const { - for(size_t i = 0; i < N; i++) - { - if((*this)[i] != other[i]) - { - return false; - } - } - return true; -} - -template -inline bool qkernel::Bitmap::operator !=(const Bitmap& other) const { - return !((*this) == other); -} - -template -inline typename qkernel::Bitmap::Reference qkernel::Bitmap::operator [](const size_t index) { - return Reference(data[index / 8], index % 8); -} - -template -inline bool qkernel::Bitmap::operator [](const size_t index) const { - return (data[index/8] & (1 << (index % 8))) == 0 ? false : true; -} - -template -inline qkernel::Bitmap qkernel::Bitmap::operator &(const Bitmap& other) const { - Bitmap result; - for(size_t i = 0; i < N; i++) - { - result[i] = (*this)[i] && other[i]; - } - return result; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::operator &=(const Bitmap& other) { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = (*this)[i] && other[i]; - } - return *this; -} - -template -inline qkernel::Bitmap qkernel::Bitmap::operator |(const Bitmap& other) const { - Bitmap result; - for(size_t i = 0; i < N; i++) - { - result[i] = (*this)[i] || other[i]; - } - return result; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::operator |=(const Bitmap& other) { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = (*this)[i] || other[i]; - } - return *this; -} - -template -inline qkernel::Bitmap qkernel::Bitmap::operator ^(const Bitmap& other) const { - Bitmap result; - for(size_t i = 0; i < N; i++) - { - result[i] = (*this)[i] ^ other[i]; - } - return result; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::operator ^=(const Bitmap& other) { - for(size_t i = 0; i < N; i++) - { - (*this)[i] = (*this)[i] ^ other[i]; - } - return *this; -} - -template -inline qkernel::Bitmap qkernel::Bitmap::operator <<(const size_t n) const { - Bitmap result; - for(size_t i = 0; i < N; i++) - { - if(i < n) - { - result[i] = false; - } - else - { - result[i] = (*this)[i-n]; - } - } - return result; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::operator <<=(const size_t n) { - for(size_t i = 0; i < N; i++) - { - if(i == 0) - { - (*this)[i] = 0; - } - else - { - (*this)[i] = (*this)[i-1]; - } - } - return *this; -} - -template -inline qkernel::Bitmap qkernel::Bitmap::operator >>(const size_t n) const { - Bitmap result; - for(size_t i = 0; i < N; i++) - { - if(i > N - n) - { - result[i] = false; - } - else - { - result[i] = (*this)[i+n]; - } - } - return result; -} - -template -inline qkernel::Bitmap& qkernel::Bitmap::operator >>=(const size_t n) { - for(size_t i = N - 1; i >= 0; i--) - { - if(i == N - 1) - { - (*this)[i] = 0; - } - else - { - (*this)[i] = (*this)[i+1]; - } - } - return *this; -} - -template -inline qkernel::Bitmap qkernel::Bitmap::operator ~() const { - Bitmap result; - for(size_t i = 0; i < N; i++) - { - result[i] = !(*this)[i]; - } - return result; -} - -#endif /* SRC_BITMAP_H_ */ diff --git a/src/error.cpp b/src/error.cpp deleted file mode 100755 index b22ff75..0000000 --- a/src/error.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Error.cpp - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#include "error.h" - -namespace qkernel { - -Error lastError; - -Error::Error() - : errorType(ErrorType::none), message("") {} - -Error::Error(ErrorType errorType) - : errorType(errorType), message("") {} - -Error::Error(ErrorType errorType, const char* message) - : errorType(errorType), message(message) {} - -ErrorType Error::getType() -{ - return errorType; -} - -const char* Error::getMessage() -{ - return message; -} - -} /* namespace qkernel */ diff --git a/src/error.h b/src/error.h deleted file mode 100755 index eeddde1..0000000 --- a/src/error.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Error.h - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#ifndef SRC_ERROR_H_ -#define SRC_ERROR_H_ - -#include "errortype.h" - -namespace qkernel { - -class Error { -public: - - Error(); - - Error(ErrorType errorType); - - Error(ErrorType errorType, const char* message); - - ErrorType getType(); - - const char* getMessage(); - -private: - - ErrorType errorType; - - const char* message; - -}; - -extern Error lastError; - -} /* namespace qkernel */ - -#endif /* SRC_ERROR_H_ */ diff --git a/src/errortype.h b/src/errortype.h deleted file mode 100755 index e4307f6..0000000 --- a/src/errortype.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ErrorType.h - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#ifndef SRC_ERRORTYPE_H_ -#define SRC_ERRORTYPE_H_ - - -enum class ErrorType -{ - none, - outOfBounds, - illegalState, - outOfMemory, - invalidArgument -}; - - -#endif /* SRC_ERRORTYPE_H_ */ From 6b1376e293041c8657f78a51ae3558c16a7b5a62 Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Thu, 9 Jul 2020 17:30:12 -0500 Subject: [PATCH 05/10] Fixed error in recipe for kernel binary. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e04ac77..2dd8120 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ - src/cstring.o src/error.o src/pagetableentry.o src/multiboot2header.o\ + src/cstring.o src/pagetableentry.o src/multiboot2header.o \ src/systeminfo.o src/memorymap.o src/entry.o src/quarkkernel.o link_script = src/linker.ld quark_bin = qkernel @@ -19,7 +19,7 @@ $(quark_img): bin/$(quark_bin) rootfs/boot/grub/grub.cfg bin/$(quark_bin): $(objs) $(link_script) mkdir -p bin/ - $(CXX) -o $@ -T $(link_script) -ffreestanding -nostdlib -O0 $^ -lgcc + $(CXX) -o $@ -T $(link_script) -ffreestanding -nostdlib -O0 $(objs) -lgcc .PHONY: clean clean: From 2c48e3397d3b32993f8a67c1eb9c0adbb296a0fa Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Thu, 9 Jul 2020 17:30:48 -0500 Subject: [PATCH 06/10] Removed extra closing brace --- src/inthandlers.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/inthandlers.cpp b/src/inthandlers.cpp index f5330b2..64eb7d7 100644 --- a/src/inthandlers.cpp +++ b/src/inthandlers.cpp @@ -14,4 +14,3 @@ void pageFaultHandler(unsigned int error) } -} From 722d6a77f566ad138b690cc71f438289bb5fc4e7 Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Thu, 9 Jul 2020 18:06:38 -0500 Subject: [PATCH 07/10] Changed name of kernel namespace --- src/addressspace.cpp | 8 +++---- src/addressspace.hpp | 4 ++-- src/buddyallocator.cpp | 42 ++++++++++++++++++------------------- src/buddyallocator.hpp | 2 +- src/interruptdescriptor.cpp | 37 +++++++++++++++++++++++++------- src/interruptdescriptor.hpp | 9 +++++--- src/memoryallocator.hpp | 2 +- src/memorymap.cpp | 14 ++++++------- src/memorymap.hpp | 2 +- src/pagetableentry.cpp | 2 +- src/pagetableentry.hpp | 2 +- src/quarkkernel.cpp | 6 +----- src/systeminfo.cpp | 6 +++--- src/systeminfo.hpp | 2 +- src/tty.cpp | 26 +++++++++++------------ src/tty.h | 2 +- 16 files changed, 93 insertions(+), 73 deletions(-) diff --git a/src/addressspace.cpp b/src/addressspace.cpp index d8663c8..8056e8a 100644 --- a/src/addressspace.cpp +++ b/src/addressspace.cpp @@ -1,13 +1,13 @@ #include "addressspace.hpp" -qkernel::AddressSpace::AddressSpace(MemoryAllocator& malloc) +kernel::AddressSpace::AddressSpace(MemoryAllocator& malloc) : malloc(malloc) { this->pageTables = (PageTableEntry*) 0xFFC00000; this->pageDirectory = (PageTableEntry*) 0xFFFFF000; } -void* qkernel::AddressSpace::mmap(void* start, size_t length) +void* kernel::AddressSpace::mmap(void* start, size_t length) { size_t tableIndex = (size_t) start / 4096; for(int i = (int) length; i > 0; i -= 4096) @@ -34,12 +34,12 @@ void* qkernel::AddressSpace::mmap(void* start, size_t length) return start; } -void qkernel::AddressSpace::munmap(void* start, size_t length) +void kernel::AddressSpace::munmap(void* start, size_t length) { } -physaddr_t qkernel::AddressSpace::getPhysicalAddress(void* virtualAddress) +physaddr_t kernel::AddressSpace::getPhysicalAddress(void* virtualAddress) const { size_t index = (size_t) virtualAddress / 4096; diff --git a/src/addressspace.hpp b/src/addressspace.hpp index de5c63e..b101cd2 100755 --- a/src/addressspace.hpp +++ b/src/addressspace.hpp @@ -7,7 +7,7 @@ #include "pagetableentry.hpp" #include "systypes.hpp" -namespace qkernel { +namespace kernel { class AddressSpace { public: @@ -37,6 +37,6 @@ private: }; -} /* namespace qkernel */ +} /* namespace kernel */ #endif diff --git a/src/buddyallocator.cpp b/src/buddyallocator.cpp index fb8a60a..c8f9f81 100755 --- a/src/buddyallocator.cpp +++ b/src/buddyallocator.cpp @@ -5,12 +5,12 @@ #define roundUp(n, m) ((n % m == 0) ? n : (n + m - (n % m))) -qkernel::BuddyAllocator::BuddyAllocator() +kernel::BuddyAllocator::BuddyAllocator() { } -qkernel::BuddyAllocator::BuddyAllocator(qkernel::MemoryMap& memmap, +kernel::BuddyAllocator::BuddyAllocator(kernel::MemoryMap& memmap, char* bitmap, size_t blockCount, size_t treeHeight) { @@ -28,7 +28,7 @@ qkernel::BuddyAllocator::BuddyAllocator(qkernel::MemoryMap& memmap, physaddr_t location = 0x100000; for(size_t i = 0; i < memmap.size() && memmap[i].getSize() > 0; i++) { - if(memmap[i].getType() != qkernel::MemoryMap::AVAILABLE) + if(memmap[i].getType() != kernel::MemoryMap::AVAILABLE) continue; if(memmap[i].getLocation() > location) location = roundUp(memmap[i].getLocation(), 4096); @@ -42,7 +42,7 @@ qkernel::BuddyAllocator::BuddyAllocator(qkernel::MemoryMap& memmap, } } -qkernel::BuddyAllocator::BuddyAllocator(char* bitmap, size_t blockSize, +kernel::BuddyAllocator::BuddyAllocator(char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight) { this->bitmap = bitmap; @@ -61,7 +61,7 @@ qkernel::BuddyAllocator::BuddyAllocator(char* bitmap, size_t blockSize, } } -physaddr_t qkernel::BuddyAllocator::allocate(size_t size) +physaddr_t kernel::BuddyAllocator::allocate(size_t size) { size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); if(height > treeHeight) // Requested block size is greater than maximum @@ -83,7 +83,7 @@ physaddr_t qkernel::BuddyAllocator::allocate(size_t size) } } -void qkernel::BuddyAllocator::free(physaddr_t location, size_t size) +void kernel::BuddyAllocator::free(physaddr_t location, size_t size) { size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); if(height <= treeHeight) @@ -97,7 +97,7 @@ void qkernel::BuddyAllocator::free(physaddr_t location, size_t size) } } -size_t qkernel::BuddyAllocator::freeBlocks() const +size_t kernel::BuddyAllocator::freeBlocks() const { size_t count = 0; for(size_t j = 0; j < blockCount; j++) @@ -110,7 +110,7 @@ size_t qkernel::BuddyAllocator::freeBlocks() const return count; } -size_t qkernel::BuddyAllocator::maxAllocationSize() const +size_t kernel::BuddyAllocator::maxAllocationSize() const { for(size_t i = treeHeight; i >= 0; i--) { @@ -125,17 +125,17 @@ size_t qkernel::BuddyAllocator::maxAllocationSize() const return 0; } -size_t qkernel::BuddyAllocator::getBlockSize() const +size_t kernel::BuddyAllocator::getBlockSize() const { return blockSize; } -size_t qkernel::BuddyAllocator::getMemorySize() const +size_t kernel::BuddyAllocator::getMemorySize() const { return blockCount; } -size_t qkernel::BuddyAllocator::findFreeBlock(size_t height) +size_t kernel::BuddyAllocator::findFreeBlock(size_t height) { for(size_t i = 0; i < (blockCount >> height); i++) { @@ -155,7 +155,7 @@ size_t qkernel::BuddyAllocator::findFreeBlock(size_t height) return INVALID; } -size_t qkernel::BuddyAllocator::split(size_t height, size_t index) +size_t kernel::BuddyAllocator::split(size_t height, size_t index) { if(height > 0 && isFree(height, index)) { @@ -170,7 +170,7 @@ size_t qkernel::BuddyAllocator::split(size_t height, size_t index) } } -size_t qkernel::BuddyAllocator::merge(size_t height, size_t index) +size_t kernel::BuddyAllocator::merge(size_t height, size_t index) { if(isFree(height, index) && isFree(height, getBuddy(index)) && height < treeHeight) { @@ -193,34 +193,34 @@ size_t qkernel::BuddyAllocator::merge(size_t height, size_t index) } } -size_t qkernel::BuddyAllocator::getBuddy(size_t index) +size_t kernel::BuddyAllocator::getBuddy(size_t index) { return index ^ 1; } -size_t qkernel::BuddyAllocator::getParent(size_t index) +size_t kernel::BuddyAllocator::getParent(size_t index) { return index / 2; } -size_t qkernel::BuddyAllocator::getChild(size_t index) +size_t kernel::BuddyAllocator::getChild(size_t index) { return index * 2; } -physaddr_t qkernel::BuddyAllocator::nodeToAddress(size_t height, size_t index) +physaddr_t kernel::BuddyAllocator::nodeToAddress(size_t height, size_t index) const { return index * (blockSize << height); } -size_t qkernel::BuddyAllocator::addressToNode(size_t height, +size_t kernel::BuddyAllocator::addressToNode(size_t height, physaddr_t location) const { return location / (blockSize << height); } -void qkernel::BuddyAllocator::reserveNode(size_t height, size_t index) +void kernel::BuddyAllocator::reserveNode(size_t height, size_t index) { size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); @@ -228,7 +228,7 @@ void qkernel::BuddyAllocator::reserveNode(size_t height, size_t index) bitmap[bit / 8] |= 1 << (bit % 8); } -void qkernel::BuddyAllocator::freeNode(size_t height, size_t index) +void kernel::BuddyAllocator::freeNode(size_t height, size_t index) { size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); @@ -236,7 +236,7 @@ void qkernel::BuddyAllocator::freeNode(size_t height, size_t index) bitmap[bit / 8] &= ~(1 << (bit % 8)); } -bool qkernel::BuddyAllocator::isFree(size_t height, size_t index) const +bool kernel::BuddyAllocator::isFree(size_t height, size_t index) const { size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); diff --git a/src/buddyallocator.hpp b/src/buddyallocator.hpp index 2be4b14..edee782 100755 --- a/src/buddyallocator.hpp +++ b/src/buddyallocator.hpp @@ -4,7 +4,7 @@ #include "memoryallocator.hpp" #include "memorymap.hpp" -namespace qkernel +namespace kernel { class BuddyAllocator : public MemoryAllocator diff --git a/src/interruptdescriptor.cpp b/src/interruptdescriptor.cpp index cbbdf79..50d9536 100644 --- a/src/interruptdescriptor.cpp +++ b/src/interruptdescriptor.cpp @@ -1,6 +1,6 @@ #include "interruptdescriptor.hpp" -qkernel::InterruptDescriptor::InterruptDescriptor() +kernel::InterruptDescriptor::InterruptDescriptor() { this->m_offset1 = 0; this->m_selector = 0; @@ -12,8 +12,7 @@ qkernel::InterruptDescriptor::InterruptDescriptor() this->m_offset2 = 0; } -qkernel::InterruptDescriptor::InterruptDescriptor(void* handler, - Type type, unsigned int dpl) +kernel::InterruptDescriptor::InterruptDescriptor(void* handler, Type type, unsigned int dpl) { uint32_t offset = (uint32_t) handler; this->m_offset1 = (uint16_t) offset; @@ -23,19 +22,41 @@ qkernel::InterruptDescriptor::InterruptDescriptor(void* handler, this->m_storage = 0; this->m_dpl = dpl; this->m_present = 0; - this->m_offset = (uint16_t) (offset >> 16); + this->m_offset2 = (uint16_t) (offset >> 16); } -bool qkernel::InterruptDescriptor::present() +bool kernel::InterruptDescriptor::present() { return m_present == 1; } -void qkernel::InterruptDescriptor::present(bool present) +void kernel::InterruptDescriptor::present(bool present) { m_present = present ? 1 : 0; } -Type qkernel::InterruptDescriptor::type() +kernel::InterruptDescriptor::Type kernel::InterruptDescriptor::type() { - + return (Type) m_type; +} + +void kernel::InterruptDescriptor::type(kernel::InterruptDescriptor::Type type) +{ + m_type = (unsigned int) type; +} + +unsigned int kernel::InterruptDescriptor::dpl() +{ + return m_dpl; +} + +void kernel::InterruptDescriptor::dpl(unsigned int dpl) +{ + m_dpl = dpl; +} + +void* kernel::InterruptDescriptor::operator=(void* rhs) +{ + uint32_t offset = (uint32_t) rhs; + m_offset1 = (uint16_t) offset; + m_offset2 = (uint16_t) (offset >> 16); } diff --git a/src/interruptdescriptor.hpp b/src/interruptdescriptor.hpp index 31edfce..65fd261 100644 --- a/src/interruptdescriptor.hpp +++ b/src/interruptdescriptor.hpp @@ -3,7 +3,7 @@ #include -namespace qkernel +namespace kernel { class InterruptDescriptor @@ -21,7 +21,7 @@ public: InterruptDescriptor(); - InterruptDescriptor(void* handler, unsigned int type, unsigned int dpl); + InterruptDescriptor(void* handler, Type type, unsigned int dpl); bool present(); @@ -30,7 +30,10 @@ public: Type type(); void type(Type type); - + + unsigned int dpl(); + + void dpl(unsigned int dpl); void* operator=(void* rhs); diff --git a/src/memoryallocator.hpp b/src/memoryallocator.hpp index b14c8a3..48ea87c 100755 --- a/src/memoryallocator.hpp +++ b/src/memoryallocator.hpp @@ -4,7 +4,7 @@ #include #include "systypes.hpp" -namespace qkernel +namespace kernel { /** diff --git a/src/memorymap.cpp b/src/memorymap.cpp index 96a5fab..2935778 100644 --- a/src/memorymap.cpp +++ b/src/memorymap.cpp @@ -1,37 +1,37 @@ #include "memorymap.hpp" -qkernel::MemoryMap::MemoryMap(qkernel::MemoryMap::Region* map, size_t entries) +kernel::MemoryMap::MemoryMap(kernel::MemoryMap::Region* map, size_t entries) { this->map = map; this->entries = entries; } -qkernel::MemoryMap::Region& qkernel::MemoryMap::operator[](size_t index) +kernel::MemoryMap::Region& kernel::MemoryMap::operator[](size_t index) { return map[index]; } -size_t qkernel::MemoryMap::size() +size_t kernel::MemoryMap::size() { return entries; } -physaddr_t qkernel::MemoryMap::Region::getLocation() +physaddr_t kernel::MemoryMap::Region::getLocation() { return location; } -size_t qkernel::MemoryMap::Region::getSize() +size_t kernel::MemoryMap::Region::getSize() { return size; } -qkernel::MemoryMap::Type qkernel::MemoryMap::Region::getType() +kernel::MemoryMap::Type kernel::MemoryMap::Region::getType() { return (Type) type; } -bool qkernel::MemoryMap::Region::contains(physaddr_t location, size_t size) +bool kernel::MemoryMap::Region::contains(physaddr_t location, size_t size) { return (location >= this->location) && (location + size <= this->location + this->size); diff --git a/src/memorymap.hpp b/src/memorymap.hpp index 6a762a7..853927a 100644 --- a/src/memorymap.hpp +++ b/src/memorymap.hpp @@ -6,7 +6,7 @@ #include "systypes.hpp" -namespace qkernel +namespace kernel { class MemoryMap diff --git a/src/pagetableentry.cpp b/src/pagetableentry.cpp index 66af515..f84c477 100755 --- a/src/pagetableentry.cpp +++ b/src/pagetableentry.cpp @@ -7,7 +7,7 @@ #include "pagetableentry.hpp" -namespace qkernel { +namespace kernel { static_assert(sizeof(PageTableEntry) == 4, "PTE structure is the wrong size!"); diff --git a/src/pagetableentry.hpp b/src/pagetableentry.hpp index 7e7a3f4..0200953 100755 --- a/src/pagetableentry.hpp +++ b/src/pagetableentry.hpp @@ -11,7 +11,7 @@ #include #include "systypes.hpp" -namespace qkernel { +namespace kernel { class PageTableEntry { public: diff --git a/src/quarkkernel.cpp b/src/quarkkernel.cpp index e9db5f5..ee6b6ce 100755 --- a/src/quarkkernel.cpp +++ b/src/quarkkernel.cpp @@ -8,11 +8,7 @@ #include "addressspace.hpp" #include "tty.h" -#if __STDC_HOSTED__ == 1 || __i686__ != 1 -#error "ERROR: This program must be compiled for a freestanding environment, and currently only supports the i686 target." -#endif - -using namespace qkernel; +using namespace kernel; extern SystemInfo system_info; extern MemoryMap::Region memory_map; diff --git a/src/systeminfo.cpp b/src/systeminfo.cpp index 889e314..0ed92e4 100644 --- a/src/systeminfo.cpp +++ b/src/systeminfo.cpp @@ -1,16 +1,16 @@ #include "systeminfo.hpp" -size_t qkernel::SystemInfo::getLowMemory() +size_t kernel::SystemInfo::getLowMemory() { return lowMemory; } -size_t qkernel::SystemInfo::getHighMemory() +size_t kernel::SystemInfo::getHighMemory() { return highMemory; } -physaddr_t qkernel::SystemInfo::getKernelBase() +physaddr_t kernel::SystemInfo::getKernelBase() { return kernelBase; } diff --git a/src/systeminfo.hpp b/src/systeminfo.hpp index 6aedfde..33ef728 100644 --- a/src/systeminfo.hpp +++ b/src/systeminfo.hpp @@ -5,7 +5,7 @@ #include "systypes.hpp" -namespace qkernel +namespace kernel { class SystemInfo diff --git a/src/tty.cpp b/src/tty.cpp index 0ae4832..dcb80d2 100644 --- a/src/tty.cpp +++ b/src/tty.cpp @@ -1,7 +1,7 @@ #include #include "tty.h" -qkernel::TTY::TTY(char* vga) +kernel::TTY::TTY(char* vga) { this->vga = vga; this->cursor = 0; @@ -9,7 +9,7 @@ qkernel::TTY::TTY(char* vga) this->base = 10; } -qkernel::TTY& qkernel::TTY::operator<<(qkernel::TTY::Format fmt) +kernel::TTY& kernel::TTY::operator<<(kernel::TTY::Format fmt) { switch(fmt) { @@ -25,42 +25,42 @@ qkernel::TTY& qkernel::TTY::operator<<(qkernel::TTY::Format fmt) } } -qkernel::TTY& qkernel::TTY::operator<<(const char* str) +kernel::TTY& kernel::TTY::operator<<(const char* str) { return printString(str); } -qkernel::TTY& qkernel::TTY::operator<<(unsigned int n) +kernel::TTY& kernel::TTY::operator<<(unsigned int n) { return printNumber(n, base, width); } -qkernel::TTY& qkernel::TTY::operator<<(int n) +kernel::TTY& kernel::TTY::operator<<(int n) { return printNumber((unsigned int) n, base, width); } -qkernel::TTY& qkernel::TTY::operator<<(void* n) +kernel::TTY& kernel::TTY::operator<<(void* n) { return printNumber((unsigned int) n, 16, 8); } -qkernel::TTY& qkernel::TTY::operator<<(char c) +kernel::TTY& kernel::TTY::operator<<(char c) { return putChar(c); } -void qkernel::TTY::setWidth(size_t width) +void kernel::TTY::setWidth(size_t width) { this->width = width; } -size_t qkernel::TTY::getWidth() +size_t kernel::TTY::getWidth() { return width; } -void qkernel::TTY::clear() +void kernel::TTY::clear() { for(int i = 0; i < 80*25; i++) { @@ -69,7 +69,7 @@ void qkernel::TTY::clear() cursor = 0; } -qkernel::TTY& qkernel::TTY::printNumber(unsigned int n, size_t base, +kernel::TTY& kernel::TTY::printNumber(unsigned int n, size_t base, size_t width) { const char* digits = "0123456789ABCDEF"; @@ -94,7 +94,7 @@ qkernel::TTY& qkernel::TTY::printNumber(unsigned int n, size_t base, return *this; } -qkernel::TTY& qkernel::TTY::printString(const char* str) +kernel::TTY& kernel::TTY::printString(const char* str) { while(*str) { @@ -104,7 +104,7 @@ qkernel::TTY& qkernel::TTY::printString(const char* str) return *this; } -qkernel::TTY& qkernel::TTY::putChar(char c) +kernel::TTY& kernel::TTY::putChar(char c) { switch(c) { diff --git a/src/tty.h b/src/tty.h index 12327ee..47b5191 100644 --- a/src/tty.h +++ b/src/tty.h @@ -3,7 +3,7 @@ #include -namespace qkernel +namespace kernel { class TTY From be7a17596db0130486dc2cadfe6f4fe5f53aa93f Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Thu, 9 Jul 2020 21:58:02 -0500 Subject: [PATCH 08/10] Added inb and outb functions --- src/pio.S | 13 +++++++++++++ src/pio.hpp | 8 ++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/pio.S create mode 100644 src/pio.hpp diff --git a/src/pio.S b/src/pio.S new file mode 100644 index 0000000..7681ee0 --- /dev/null +++ b/src/pio.S @@ -0,0 +1,13 @@ +.global outb +outb: + mov 4(%esp), %dx + mov 8(%esp), %al + out %al, %dx + ret + +.global inb +inb: + mov 4(%esp), %dx + xor %eax, %eax + in %dx, %al + ret \ No newline at end of file diff --git a/src/pio.hpp b/src/pio.hpp new file mode 100644 index 0000000..68aed33 --- /dev/null +++ b/src/pio.hpp @@ -0,0 +1,8 @@ +#ifndef PIO_H +#define PIO_H + +extern "C" void outb(short port, char data); + +extern "C" char inb(short port); + +#endif \ No newline at end of file From cff89659403b04597f7bb4a472b632f374692a4d Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Thu, 9 Jul 2020 21:58:52 -0500 Subject: [PATCH 09/10] Added interrupt handling --- Makefile | 7 ++++--- src/entry.S | 29 +++++++++++++++++++++++++++-- src/interruptdescriptor.cpp | 8 ++++---- src/interruptdescriptor.hpp | 10 +++++----- src/inthandlers.cpp | 27 ++++++++++++++++++++++----- src/inthandlers.hpp | 8 ++++++-- src/quarkkernel.cpp | 33 +++++++++++++++++++++++++-------- 7 files changed, 93 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 2dd8120..ce2cb91 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ -objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ +objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ src/cstring.o src/pagetableentry.o src/multiboot2header.o \ - src/systeminfo.o src/memorymap.o src/entry.o src/quarkkernel.o + src/systeminfo.o src/memorymap.o src/interruptdescriptor.o \ + src/inthandlers.o src/pio.o src/entry.o src/quarkkernel.o link_script = src/linker.ld quark_bin = qkernel quark_img = quark.iso @@ -8,7 +9,7 @@ quark_img = quark.iso CXX = i686-elf-g++ CC = i686-elf-gcc -CPPFLAGS = -ffreestanding -O2 -Wall -fno-exceptions -fno-rtti -ggdb +CPPFLAGS = -ffreestanding -mgeneral-regs-only -O0 -Wall -fno-exceptions -fno-rtti -ggdb .PHONY: all all: $(quark_img) diff --git a/src/entry.S b/src/entry.S index 92768e1..0c9b030 100755 --- a/src/entry.S +++ b/src/entry.S @@ -2,7 +2,23 @@ .include "src/multiboot2header.S" .section .rodata - + +gdt: +.long 0, 0 +.short 0xFFFF +.short 0x0000 +.short 0x9A00 +.short 0x00CF +.short 0xFFFF +.short 0x0000 +.short 0x9200 +.short 0x00CF + +gdt_info: +.short 23 +.long gdt + +.align 16 idt_info: .short idt_end - idt - 1 .long idt @@ -199,9 +215,18 @@ s_end: # Initialize stack mov $stackTop, %esp - + lgdt gdt_info lidt idt_info + jmp $8, $.ldcs +.ldcs: + mov $16, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %gs + mov %ax, %fs + mov %ax, %ss + mov $_bootCmdLine, %eax push %eax diff --git a/src/interruptdescriptor.cpp b/src/interruptdescriptor.cpp index 50d9536..866bd6f 100644 --- a/src/interruptdescriptor.cpp +++ b/src/interruptdescriptor.cpp @@ -16,13 +16,13 @@ kernel::InterruptDescriptor::InterruptDescriptor(void* handler, Type type, unsig { uint32_t offset = (uint32_t) handler; this->m_offset1 = (uint16_t) offset; - this->m_selector = 1; + 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 = 0; - this->m_offset2 = (uint16_t) (offset >> 16); + this->m_present = 1; + this->m_offset2 = offset >> 16; } bool kernel::InterruptDescriptor::present() @@ -58,5 +58,5 @@ void* kernel::InterruptDescriptor::operator=(void* rhs) { uint32_t offset = (uint32_t) rhs; m_offset1 = (uint16_t) offset; - m_offset2 = (uint16_t) (offset >> 16); + m_offset2 = (offset >> 16); } diff --git a/src/interruptdescriptor.hpp b/src/interruptdescriptor.hpp index 65fd261..c4365fe 100644 --- a/src/interruptdescriptor.hpp +++ b/src/interruptdescriptor.hpp @@ -12,11 +12,11 @@ public: enum Type { - TASK32 = 5, - TRAP32 = 15, - INT32 = 14, - TRAP16 = 7, - INT16 = 6 + TASK32 = 5, + TRAP32 = 15, + INT32 = 14, + TRAP16 = 7, + INT16 = 6 }; InterruptDescriptor(); diff --git a/src/inthandlers.cpp b/src/inthandlers.cpp index 64eb7d7..bf780e8 100644 --- a/src/inthandlers.cpp +++ b/src/inthandlers.cpp @@ -1,16 +1,33 @@ #include "inthandlers.hpp" -extern "C" +char* display = (char*) 0xC00B8000; + +__attribute__ ((interrupt)) +void divisionByZero(void* frame) +{ + *display = 'z'; + display += 2; +} + + __attribute__ ((interrupt)) void gpFaultHandler(void* frame, unsigned int error) { - + *display = 'a'; + asm("hlt"); } -extern "C" __attribute__ ((interrupt)) -void pageFaultHandler(unsigned int error) +void pageFaultHandler(void* frame, unsigned int error) { - + *display = '0'; + //asm("hlt"); +} + +__attribute__ ((interrupt)) +void doubleFaultHandler(void* frame, unsigned int error) +{ + *display = '#'; + //asm("hlt"); } diff --git a/src/inthandlers.hpp b/src/inthandlers.hpp index 405ad56..10f085b 100644 --- a/src/inthandlers.hpp +++ b/src/inthandlers.hpp @@ -1,12 +1,16 @@ #ifndef INTHANDLERS_H #define INTHANDLERS_H -extern "C" +__attribute__ ((interrupt)) +void divisionByZero(void* frame); + __attribute__ ((interrupt)) void gpFaultHandler(void* frame, unsigned int error); -extern "C" __attribute__ ((interrupt)) void pageFaultHandler(void* frame, unsigned int error); +__attribute__ ((interrupt)) +void doubleFaultHandler(void* frame, unsigned int error); + #endif diff --git a/src/quarkkernel.cpp b/src/quarkkernel.cpp index ee6b6ce..544c33a 100755 --- a/src/quarkkernel.cpp +++ b/src/quarkkernel.cpp @@ -6,30 +6,47 @@ #include "memorymap.hpp" #include "buddyallocator.hpp" #include "addressspace.hpp" +#include "interruptdescriptor.hpp" +#include "inthandlers.hpp" +#include "pio.hpp" #include "tty.h" using namespace kernel; extern SystemInfo system_info; extern MemoryMap::Region memory_map; +extern InterruptDescriptor idt; + +extern "C" void __cxa_pure_virtual() +{ + +} void main(char* cmdline) { - TTY tty((char*) 0xC00B8000); + TTY tty((char*) 0xC00B8000); tty << "--Quark Kernel--\n"; tty << "Low memory: \t" << (int) system_info.getLowMemory() << " KiB\n"; tty << "High memory:\t" << (int) system_info.getHighMemory() << " KiB\n"; tty << "Type\t\tLocation\t\tSize\n"; MemoryMap memmap(&memory_map, 16); - for(size_t i = 0; i < memmap.size() && memmap[i].getSize() > 0; i++) + for(size_t i = 0; i < memmap.size() && memmap[i].getSize() > 0; i++) { - tty << (int) memmap[i].getType() << "\t\t\t" - << (void*) memmap[i].getLocation() << "\t\t" - << (int) memmap[i].getSize() << "\n"; + tty << (int) memmap[i].getType() << "\t\t\t"; + tty << (void*) memmap[i].getLocation() << "\t\t"; + tty << (int) memmap[i].getSize() << "\n"; } - BuddyAllocator alloc(memmap, (char*) 0xC0000000, - system_info.getHighMemory() / 4 + 256, 6); + BuddyAllocator alloc(memmap, (char*) 0xC0000000, system_info.getHighMemory() / 4 + 256, 6); AddressSpace vmem(alloc); - tty << vmem.mmap((void*) 0x80000000, 0x10000) << '\n'; + vmem.mmap((void*) 0x80000000, 0x10000); + InterruptDescriptor* interruptTable = &idt; + interruptTable[0] = InterruptDescriptor((void*) &divisionByZero, InterruptDescriptor::INT32, 0); + interruptTable[8] = InterruptDescriptor((void*) &doubleFaultHandler, InterruptDescriptor::INT32, 0); + interruptTable[14] = InterruptDescriptor((void*) &pageFaultHandler, InterruptDescriptor::INT32, 0); + //for(int i = 1; i < 32; i++) + // interruptTable[i] = InterruptDescriptor((void*) &pageFaultHandler, InterruptDescriptor::INT32, 0); + outb(0xa1, 0xff); + outb(0x21, 0xff); + asm("sti"); tty << "Nothing left to do. Hanging.\n"; } From 8ff5b556946c9a03c2447de420c5477f5d79904e Mon Sep 17 00:00:00 2001 From: Nathan Giddings Date: Wed, 15 Jul 2020 06:50:03 -0500 Subject: [PATCH 10/10] Moved interrupt handling to subdir --- .gitignore | 8 +++--- Makefile | 27 +++++-------------- src/Makefile | 18 +++++++++++++ src/entry.S | 2 +- src/interrupts/Makefile | 9 +++++++ src/interrupts/interrupts.hpp | 19 +++++++++++++ src/interrupts/x86/idt.S | 21 +++++++++++++++ src/interrupts/x86/idt.hpp | 10 +++++++ .../x86}/interruptdescriptor.cpp | 0 .../x86}/interruptdescriptor.hpp | 0 src/interrupts/x86/interrupts.cpp | 19 +++++++++++++ src/{ => interrupts/x86}/inthandlers.cpp | 1 - src/{ => interrupts/x86}/inthandlers.hpp | 0 src/quarkkernel.cpp | 10 ------- 14 files changed, 108 insertions(+), 36 deletions(-) create mode 100644 src/Makefile create mode 100644 src/interrupts/Makefile create mode 100644 src/interrupts/interrupts.hpp create mode 100644 src/interrupts/x86/idt.S create mode 100644 src/interrupts/x86/idt.hpp rename src/{ => interrupts/x86}/interruptdescriptor.cpp (100%) rename src/{ => interrupts/x86}/interruptdescriptor.hpp (100%) create mode 100644 src/interrupts/x86/interrupts.cpp rename src/{ => interrupts/x86}/inthandlers.cpp (99%) rename src/{ => interrupts/x86}/inthandlers.hpp (100%) diff --git a/.gitignore b/.gitignore index 63e9dc8..e6d5185 100755 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ -bin/* -src/*.o quark.iso -src/*~ +src/quark-kernel +src/interrupts/libinterrupts.a +*.o *~ -rootfs +rootfs/ test/ \ No newline at end of file diff --git a/Makefile b/Makefile index ce2cb91..d7cdb0d 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,14 @@ -objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ - src/cstring.o src/pagetableentry.o src/multiboot2header.o \ - src/systeminfo.o src/memorymap.o src/interruptdescriptor.o \ - src/inthandlers.o src/pio.o src/entry.o src/quarkkernel.o -link_script = src/linker.ld -quark_bin = qkernel -quark_img = quark.iso - -CXX = i686-elf-g++ -CC = i686-elf-gcc - -CPPFLAGS = -ffreestanding -mgeneral-regs-only -O0 -Wall -fno-exceptions -fno-rtti -ggdb - .PHONY: all -all: $(quark_img) +all: quark.iso -$(quark_img): bin/$(quark_bin) rootfs/boot/grub/grub.cfg - cp bin/$(quark_bin) rootfs/apps +quark.iso: src/quark-kernel + cp src/quark-kernel rootfs/apps grub-mkrescue -o $@ rootfs -bin/$(quark_bin): $(objs) $(link_script) - mkdir -p bin/ - $(CXX) -o $@ -T $(link_script) -ffreestanding -nostdlib -O0 $(objs) -lgcc +src/quark-kernel: + make -C src .PHONY: clean clean: - rm -f $(objs) bin/$(quark_bin) $(quark_img) + make -C src clean + rm -f quark.iso diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..e10855e --- /dev/null +++ b/src/Makefile @@ -0,0 +1,18 @@ +objs = addressspace.o tty.o buddyallocator.o math.o cstring.o pagetableentry.o multiboot2header.o systeminfo.o memorymap.o pio.o entry.o quarkkernel.o + +CXX = i686-elf-g++ +CC = i686-elf-gcc + +CXXFLAGS = -ffreestanding -mgeneral-regs-only -O0 -Wall -fno-exceptions -fno-rtti -ggdb +LDFLAGS = -T linker.ld -lgcc -nostdlib + +quark-kernel: $(objs) linker.ld interrupts/libinterrupts.a + $(CXX) -o $@ $(LDFLAGS) interrupts/libinterrupts.a $(objs) + +interrupts/libinterrupts.a: + make -C interrupts CXX="$(CXX)" CC="$(CC)" CXXFLAGS="$(CXXFLAGS)" + +.PHONY: clean +clean: + make -C interrupts clean + rm -f $(objs) quark-kernel \ No newline at end of file diff --git a/src/entry.S b/src/entry.S index 0c9b030..2778259 100755 --- a/src/entry.S +++ b/src/entry.S @@ -1,5 +1,5 @@ .section .multiboot -.include "src/multiboot2header.S" +.include "multiboot2header.S" .section .rodata diff --git a/src/interrupts/Makefile b/src/interrupts/Makefile new file mode 100644 index 0000000..c818c6f --- /dev/null +++ b/src/interrupts/Makefile @@ -0,0 +1,9 @@ +objs = x86/inthandlers.o x86/interruptdescriptor.o x86/idt.o x86/interrupts.o +archive = libinterrupts.a + +$(archive): $(objs) + i686-elf-ar rcs $@ $^ + +.PHONY: clean +clean: + rm -f $(archive) $(objs) \ No newline at end of file diff --git a/src/interrupts/interrupts.hpp b/src/interrupts/interrupts.hpp new file mode 100644 index 0000000..173a002 --- /dev/null +++ b/src/interrupts/interrupts.hpp @@ -0,0 +1,19 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +namespace kernel +{ + class Interrupts + { + public: + + Interrupts(); + + void enable(); + + void disable(); + + }; +} + +#endif \ No newline at end of file diff --git a/src/interrupts/x86/idt.S b/src/interrupts/x86/idt.S new file mode 100644 index 0000000..a76f770 --- /dev/null +++ b/src/interrupts/x86/idt.S @@ -0,0 +1,21 @@ +.section .bss + +.align 8 +.global idt +idt: +.skip 8 * 256 +idt_end: + +.section .rodata + +.idt_info: +.short idt_end - idt - 1 +.long idt + +.section .text + +.global _lidt +.type _lidt, @function +_lidt: + + ret \ No newline at end of file diff --git a/src/interrupts/x86/idt.hpp b/src/interrupts/x86/idt.hpp new file mode 100644 index 0000000..2c1cf0f --- /dev/null +++ b/src/interrupts/x86/idt.hpp @@ -0,0 +1,10 @@ +#ifndef IDT_H +#define IDT_H + +#include "interruptdescriptor.hpp" + +extern kernel::InterruptDescriptor idt[256]; + +extern "C" void _lidt(); + +#endif \ No newline at end of file diff --git a/src/interruptdescriptor.cpp b/src/interrupts/x86/interruptdescriptor.cpp similarity index 100% rename from src/interruptdescriptor.cpp rename to src/interrupts/x86/interruptdescriptor.cpp diff --git a/src/interruptdescriptor.hpp b/src/interrupts/x86/interruptdescriptor.hpp similarity index 100% rename from src/interruptdescriptor.hpp rename to src/interrupts/x86/interruptdescriptor.hpp diff --git a/src/interrupts/x86/interrupts.cpp b/src/interrupts/x86/interrupts.cpp new file mode 100644 index 0000000..971e6a8 --- /dev/null +++ b/src/interrupts/x86/interrupts.cpp @@ -0,0 +1,19 @@ +#include "../interrupts.hpp" +#include "idt.hpp" + +kernel::Interrupts::Interrupts() +{ + // Load interrupt handlers + // Configure PIC + _lidt(); +} + +inline void kernel::Interrupts::enable() +{ + asm("sti"); +} + +inline void kernel::Interrupts::disable() +{ + asm("cli"); +} \ No newline at end of file diff --git a/src/inthandlers.cpp b/src/interrupts/x86/inthandlers.cpp similarity index 99% rename from src/inthandlers.cpp rename to src/interrupts/x86/inthandlers.cpp index bf780e8..59ce3ad 100644 --- a/src/inthandlers.cpp +++ b/src/interrupts/x86/inthandlers.cpp @@ -9,7 +9,6 @@ void divisionByZero(void* frame) display += 2; } - __attribute__ ((interrupt)) void gpFaultHandler(void* frame, unsigned int error) { diff --git a/src/inthandlers.hpp b/src/interrupts/x86/inthandlers.hpp similarity index 100% rename from src/inthandlers.hpp rename to src/interrupts/x86/inthandlers.hpp diff --git a/src/quarkkernel.cpp b/src/quarkkernel.cpp index 544c33a..d607169 100755 --- a/src/quarkkernel.cpp +++ b/src/quarkkernel.cpp @@ -6,8 +6,6 @@ #include "memorymap.hpp" #include "buddyallocator.hpp" #include "addressspace.hpp" -#include "interruptdescriptor.hpp" -#include "inthandlers.hpp" #include "pio.hpp" #include "tty.h" @@ -15,7 +13,6 @@ using namespace kernel; extern SystemInfo system_info; extern MemoryMap::Region memory_map; -extern InterruptDescriptor idt; extern "C" void __cxa_pure_virtual() { @@ -39,14 +36,7 @@ void main(char* cmdline) BuddyAllocator alloc(memmap, (char*) 0xC0000000, system_info.getHighMemory() / 4 + 256, 6); AddressSpace vmem(alloc); vmem.mmap((void*) 0x80000000, 0x10000); - InterruptDescriptor* interruptTable = &idt; - interruptTable[0] = InterruptDescriptor((void*) &divisionByZero, InterruptDescriptor::INT32, 0); - interruptTable[8] = InterruptDescriptor((void*) &doubleFaultHandler, InterruptDescriptor::INT32, 0); - interruptTable[14] = InterruptDescriptor((void*) &pageFaultHandler, InterruptDescriptor::INT32, 0); - //for(int i = 1; i < 32; i++) - // interruptTable[i] = InterruptDescriptor((void*) &pageFaultHandler, InterruptDescriptor::INT32, 0); outb(0xa1, 0xff); outb(0x21, 0xff); - asm("sti"); tty << "Nothing left to do. Hanging.\n"; }