Kernel: Start working on heap
This commit is contained in:
		
							parent
							
								
									6a3b3213cf
								
							
						
					
					
						commit
						633929629c
					
				|  | @ -26,6 +26,7 @@ set(KERNEL_SOURCES | |||
| 	kernel/Input/PS2Keymap.cpp | ||||
| 	kernel/InterruptController.cpp | ||||
| 	kernel/kernel.cpp | ||||
| 	kernel/Memory/Heap.cpp | ||||
| 	kernel/Memory/kmalloc.cpp | ||||
| 	kernel/PCI.cpp | ||||
| 	kernel/PIC.cpp | ||||
|  |  | |||
|  | @ -0,0 +1,61 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/NoCopyMove.h> | ||||
| #include <BAN/Vector.h> | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #define PAGE_SIZE 4096 | ||||
| 
 | ||||
| namespace Kernel::Memory | ||||
| { | ||||
| 
 | ||||
| 	using paddr_t = uintptr_t; | ||||
| 
 | ||||
| 	class PhysicalRange | ||||
| 	{ | ||||
| 	public: | ||||
| 		static constexpr paddr_t invalid = ~paddr_t(0); | ||||
| 
 | ||||
| 	public: | ||||
| 		PhysicalRange(paddr_t, size_t); | ||||
| 		paddr_t reserve_page(); | ||||
| 		void release_page(paddr_t); | ||||
| 
 | ||||
| 		paddr_t start() const { return m_start + m_list_pages  * PAGE_SIZE; } | ||||
| 		paddr_t end() const   { return m_start + m_total_pages * PAGE_SIZE; } | ||||
| 		uint64_t pages() const { return m_reservable_pages; } | ||||
| 
 | ||||
| 	private: | ||||
| 		paddr_t page_address(uint64_t) const; | ||||
| 
 | ||||
| 	private: | ||||
| 		paddr_t m_start	{ 0 }; | ||||
| 		size_t m_size	{ 0 }; | ||||
| 
 | ||||
| 		uint64_t m_total_pages		{ 0 }; | ||||
| 		uint64_t m_reservable_pages	{ 0 }; | ||||
| 		uint64_t m_list_pages		{ 0 }; | ||||
| 
 | ||||
| 		uint64_t* m_free_list { nullptr }; | ||||
| 		uint64_t* m_used_list { nullptr }; | ||||
| 	}; | ||||
| 	 | ||||
| 	class Heap | ||||
| 	{ | ||||
| 		BAN_NON_COPYABLE(Heap); | ||||
| 		BAN_NON_MOVABLE(Heap); | ||||
| 
 | ||||
| 	public: | ||||
| 		static void initialize(); | ||||
| 		static Heap& get(); | ||||
| 
 | ||||
| 	private: | ||||
| 		Heap() = default; | ||||
| 		void initialize_impl(); | ||||
| 
 | ||||
| 	private: | ||||
| 		BAN::Vector<PhysicalRange> m_physical_ranges; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,103 @@ | |||
| #include <kernel/Memory/Heap.h> | ||||
| #include <kernel/Memory/MMU.h> | ||||
| #include <kernel/multiboot.h> | ||||
| 
 | ||||
| extern uint8_t g_kernel_end[]; | ||||
| 
 | ||||
| namespace Kernel::Memory | ||||
| { | ||||
| 
 | ||||
| 	PhysicalRange::PhysicalRange(paddr_t start, size_t size) | ||||
| 	{ | ||||
| 		ASSERT(start + size > (paddr_t)g_kernel_end); | ||||
| 
 | ||||
| 		// Align start to page boundary and after the kernel memory
 | ||||
| 		m_start = BAN::Math::max(start, (paddr_t)g_kernel_end); | ||||
| 		if (auto rem = m_start % PAGE_SIZE) | ||||
| 			m_start += PAGE_SIZE - rem; | ||||
| 
 | ||||
| 		// Align size to page boundary
 | ||||
| 		m_size = size - (m_start - start); | ||||
| 		if (auto rem = m_size % PAGE_SIZE) | ||||
| 			m_size -= rem; | ||||
| 
 | ||||
| 		// FIXME: if total pages is just over multiple of (4096/sizeof(uint64_t)) we might make
 | ||||
| 		//        couple of pages unallocatable
 | ||||
| 		m_total_pages		= m_size / PAGE_SIZE; | ||||
| 		m_list_pages		= BAN::Math::div_round_up<uint64_t>(m_total_pages * sizeof(uint64_t), PAGE_SIZE); | ||||
| 		m_reservable_pages	= m_total_pages - m_list_pages; | ||||
| 
 | ||||
| 		MMU::get().allocate_range(m_start, m_list_pages * PAGE_SIZE, MMU::Flags::Present); | ||||
| 
 | ||||
| 		// Initialize free list with every page pointing to the next one
 | ||||
| 		uint64_t* list_ptr = (uint64_t*)m_start; | ||||
| 		for (uint64_t i = 0; i < m_reservable_pages - 1; i++) | ||||
| 		{ | ||||
| 			*list_ptr++ = i + 1; | ||||
| 			//dprintln("{}/{}", i, m_reservable_pages);
 | ||||
| 		} | ||||
| 
 | ||||
| 		*list_ptr = invalid; | ||||
| 		m_free_list = (uint64_t*)m_start; | ||||
| 
 | ||||
| 		m_used_list = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	paddr_t PhysicalRange::reserve_page() | ||||
| 	{ | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void PhysicalRange::release_page(paddr_t) | ||||
| 	{ | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	}	 | ||||
| 
 | ||||
| 	paddr_t PhysicalRange::page_address(uint64_t page_index) const | ||||
| 	{ | ||||
| 		ASSERT(page_index < m_reservable_pages); | ||||
| 		return m_start + (page_index + m_list_pages) * PAGE_SIZE; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	static Heap* s_instance = nullptr; | ||||
| 
 | ||||
| 	void Heap::initialize() | ||||
| 	{ | ||||
| 		ASSERT(s_instance == nullptr); | ||||
| 		s_instance = new Heap; | ||||
| 		ASSERT(s_instance); | ||||
| 		s_instance->initialize_impl(); | ||||
| 	} | ||||
| 
 | ||||
| 	Heap& Heap::get() | ||||
| 	{ | ||||
| 		ASSERT(s_instance); | ||||
| 		return *s_instance; | ||||
| 	} | ||||
| 
 | ||||
| 	void Heap::initialize_impl() | ||||
| 	{ | ||||
| 		if (!(g_multiboot_info->flags & (1 << 6))) | ||||
| 			Kernel::panic("Bootloader did not provide a memory map"); | ||||
| 		 | ||||
| 		for (size_t i = 0; i < g_multiboot_info->mmap_length;) | ||||
| 		{ | ||||
| 			multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(g_multiboot_info->mmap_addr + i); | ||||
| 
 | ||||
| 			if (mmmt->type == 1) | ||||
| 			{ | ||||
| 				// We can't use the memory ovelapping with kernel
 | ||||
| 				if (mmmt->base_addr + mmmt->length > (paddr_t)g_kernel_end) | ||||
| 					MUST(m_physical_ranges.push_back({ mmmt->base_addr, mmmt->length })); | ||||
| 			} | ||||
| 
 | ||||
| 			i += mmmt->size + sizeof(uint32_t); | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto& range : m_physical_ranges) | ||||
| 			dprintln("RAM {8H}->{8H}, {} pages ({}.{} MB)", range.start(), range.end(), range.pages(), range.pages() * PAGE_SIZE / (1 << 20), range.pages() * PAGE_SIZE % (1 << 20) * 100 / (1 << 20)); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -8,6 +8,7 @@ | |||
| #include <kernel/Input/PS2Controller.h> | ||||
| #include <kernel/InterruptController.h> | ||||
| #include <kernel/kprint.h> | ||||
| #include <kernel/Memory/Heap.h> | ||||
| #include <kernel/Memory/kmalloc.h> | ||||
| #include <kernel/Memory/MMU.h> | ||||
| #include <kernel/multiboot.h> | ||||
|  | @ -136,6 +137,9 @@ extern "C" void kernel_main() | |||
| 	MMU::intialize(); | ||||
| 	dprintln("MMU initialized"); | ||||
| 
 | ||||
| 	Memory::Heap::initialize(); | ||||
| 	dprintln("Heap initialzed"); | ||||
| 
 | ||||
| 	parse_command_line(); | ||||
| 	dprintln("command line parsed, root='{}'", cmdline.root); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue