forked from Bananymous/banan-os
				
			Kernel: kmalloc has now somewhat dynamic storage
Allocations bigger than PAGE_SIZE and those not forced to be identity mapped are now done on a GeneralAllocator. This allows us to use kmalloc for big allocations; bigger than the fixed 1 MiB storage. This is still a hack and the whole kmalloc will have to be rewritten at some point, but for now this does the job :D
This commit is contained in:
		
							parent
							
								
									388f530edd
								
							
						
					
					
						commit
						5e123031aa
					
				|  | @ -137,6 +137,21 @@ namespace IDT | |||
| 
 | ||||
| 	extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs) | ||||
| 	{ | ||||
| 		if (isr == ISR::PageFault) | ||||
| 		{ | ||||
| 			using namespace Kernel; | ||||
| 			 | ||||
| 			vaddr_t vaddr = regs->cr2 & PAGE_ADDR_MASK; | ||||
| 
 | ||||
| 			if (!PageTable::kernel().is_page_free(vaddr)) | ||||
| 			{ | ||||
| 				auto paddr = kmalloc_paddr_of(vaddr); | ||||
| 				ASSERT(paddr.has_value()); | ||||
| 				PageTable::current().map_page_at(paddr.value(), vaddr, PageTable::Flags::ReadWrite | PageTable::Flags::Present); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		pid_t tid = Kernel::Scheduler::current_tid(); | ||||
| 		pid_t pid = tid ? Kernel::Process::current().pid() : 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ namespace Kernel | |||
| 
 | ||||
| 	static uint64_t* allocate_page_aligned_page() | ||||
| 	{ | ||||
| 		void* page = kmalloc(PAGE_SIZE, PAGE_SIZE); | ||||
| 		void* page = kmalloc(PAGE_SIZE, PAGE_SIZE, true); | ||||
| 		ASSERT(page); | ||||
| 		memset(page, 0, PAGE_SIZE); | ||||
| 		return (uint64_t*)page; | ||||
|  |  | |||
|  | @ -1,10 +1,15 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/Optional.h> | ||||
| #include <kernel/Memory/Types.h> | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| void kmalloc_initialize(); | ||||
| void kmalloc_dump_info(); | ||||
| 
 | ||||
| void* kmalloc(size_t); | ||||
| void* kmalloc(size_t, size_t); | ||||
| void* kmalloc(size_t size); | ||||
| void* kmalloc(size_t size, size_t align, bool force_identity_map = false); | ||||
| void kfree(void*); | ||||
| 
 | ||||
| BAN::Optional<Kernel::paddr_t> kmalloc_paddr_of(Kernel::vaddr_t); | ||||
|  |  | |||
|  | @ -1,16 +1,21 @@ | |||
| #include <BAN/Errors.h> | ||||
| #include <kernel/CriticalScope.h> | ||||
| #include <kernel/kprint.h> | ||||
| #include <kernel/Memory/GeneralAllocator.h> | ||||
| #include <kernel/Memory/kmalloc.h> | ||||
| 
 | ||||
| #include <kernel/Thread.h> | ||||
| 
 | ||||
| #define MB (1 << 20) | ||||
| 
 | ||||
| extern uint8_t g_kernel_end[]; | ||||
| 
 | ||||
| static constexpr size_t s_kmalloc_min_align = alignof(max_align_t); | ||||
| 
 | ||||
| static uint8_t s_kmalloc_storage[2 * MB]; | ||||
| 
 | ||||
| static BAN::UniqPtr<Kernel::GeneralAllocator> s_general_allocator; | ||||
| 
 | ||||
| struct kmalloc_node | ||||
| { | ||||
| 	void set_align(ptrdiff_t align)			{ m_align = align; } | ||||
|  | @ -277,7 +282,7 @@ static void* kmalloc_impl(size_t size, size_t align) | |||
| 
 | ||||
| void* kmalloc(size_t size) | ||||
| { | ||||
| 	return kmalloc(size, s_kmalloc_min_align); | ||||
| 	return kmalloc(size, s_kmalloc_min_align, false); | ||||
| } | ||||
| 
 | ||||
| static constexpr bool is_power_of_two(size_t value) | ||||
|  | @ -287,16 +292,30 @@ static constexpr bool is_power_of_two(size_t value) | |||
| 	return (value & (value - 1)) == 0; | ||||
| } | ||||
| 
 | ||||
| void* kmalloc(size_t size, size_t align) | ||||
| void* kmalloc(size_t size, size_t align, bool force_indentity_map) | ||||
| { | ||||
| 	const kmalloc_info& info = s_kmalloc_info; | ||||
| 
 | ||||
| 	ASSERT(is_power_of_two(align)); | ||||
| 	if (align < s_kmalloc_min_align) | ||||
| 		align = s_kmalloc_min_align; | ||||
| 	 | ||||
| 	ASSERT(align <= PAGE_SIZE); | ||||
| 
 | ||||
| 	Kernel::CriticalScope critical; | ||||
| 
 | ||||
| 	// FIXME: this is a hack to make more dynamic kmalloc memory
 | ||||
| 	if (size > PAGE_SIZE && !force_indentity_map) | ||||
| 	{ | ||||
| 		using namespace Kernel; | ||||
| 
 | ||||
| 		if (!s_general_allocator) | ||||
| 			s_general_allocator = MUST(GeneralAllocator::create(PageTable::kernel(), (vaddr_t)g_kernel_end)); | ||||
| 		 | ||||
| 		auto vaddr = s_general_allocator->allocate(size); | ||||
| 		if (vaddr) | ||||
| 			return (void*)vaddr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (size == 0 || size >= info.size) | ||||
| 		goto no_memory; | ||||
| 
 | ||||
|  | @ -331,6 +350,9 @@ void kfree(void* address) | |||
| 
 | ||||
| 	Kernel::CriticalScope critical; | ||||
| 
 | ||||
| 	if (s_general_allocator && s_general_allocator->deallocate((Kernel::vaddr_t)address)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (s_kmalloc_fixed_info.base <= address_uint && address_uint < s_kmalloc_fixed_info.end) | ||||
| 	{ | ||||
| 		auto& info = s_kmalloc_fixed_info; | ||||
|  | @ -386,4 +408,21 @@ void kfree(void* address) | |||
| 		Kernel::panic("Trying to free a pointer {8H} outsize of kmalloc memory", address); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| } | ||||
| 
 | ||||
| BAN::Optional<Kernel::paddr_t> kmalloc_paddr_of(Kernel::vaddr_t vaddr) | ||||
| { | ||||
| 	using namespace Kernel; | ||||
| 
 | ||||
| 	if (s_general_allocator) | ||||
| 	{ | ||||
| 		auto paddr = s_general_allocator->paddr_of(vaddr); | ||||
| 		if (paddr.has_value()) | ||||
| 			return paddr.value(); | ||||
| 	} | ||||
| 
 | ||||
| 	if ((vaddr_t)s_kmalloc_storage <= vaddr && vaddr < (vaddr_t)s_kmalloc_storage + sizeof(s_kmalloc_storage)) | ||||
| 		return V2P(vaddr); | ||||
| 
 | ||||
| 	return {}; | ||||
| } | ||||
|  |  | |||
|  | @ -133,6 +133,9 @@ extern "C" void kernel_main() | |||
| 	PageTable::initialize(); | ||||
| 	dprintln("PageTable initialized"); | ||||
| 
 | ||||
| 	Heap::initialize(); | ||||
| 	dprintln("Heap initialzed"); | ||||
| 
 | ||||
| 	TerminalDriver* terminal_driver = VesaTerminalDriver::create(); | ||||
| 	ASSERT(terminal_driver); | ||||
| 	dprintln("VESA initialized"); | ||||
|  | @ -141,9 +144,6 @@ extern "C" void kernel_main() | |||
| 	ASSERT(tty1); | ||||
| 	dprintln("TTY initialized"); | ||||
| 
 | ||||
| 	Heap::initialize(); | ||||
| 	dprintln("Heap initialzed"); | ||||
| 
 | ||||
| 	parse_command_line(); | ||||
| 	dprintln("command line parsed, root='{}'", cmdline.root); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue