From cc2f1b58f59b5f42a34373dd98f0f5f85f6f831d Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Sat, 1 Aug 2020 04:52:59 +0900 Subject: [PATCH] kernel/arch: Add comments describing how the _phys_alloc(), pg_frame_alloc_start(), pg_frame_alloc_end(), pg_frame_free() functions work --- kernel/arch/paging.c | 109 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c index 7509d27..d0eb3c4 100644 --- a/kernel/arch/paging.c +++ b/kernel/arch/paging.c @@ -66,6 +66,40 @@ int _pg_dir_pagesize(pg_dir_t*, u32_t, u32_t*); int _pg_dir_xfer(pg_dir_t*, void*, pg_dir_t*, void*, u32_t); static int _pg_dir_heap_map(pg_dir_t*, u32_t); +/* + * _phys_alloc() - Dynamic memory allocator for linear memory + * + * SYNOPSIS + * void* _phys_alloc(u32_t size, u32_t align); + * + * DESCRIPTION + * The _phys_alloc() function dynamically allocates linear memory. This function is intended + * to be used for memory allocations before the kernel heap has been initialized. This memory + * allocator is very primitive and is meant for allocations that will never be freed, such as + * the kernel page directory. Allocations made by this allocator will be placed in memory after + * ther kernel's BSS segment. Once the kernel page directory has been created, this memory + * region will be included in the kernel heap segment. However, the kernel heap structures will + * be allocated in memory behind all physical alocations, which means that they will not be + * accounted for by the kernel heap. + * This function will allocate `size' bytes of memory from linear memory (which means physical + * memory in absence of paging). If alignment is desired (i.e. `align' is non-zero), the start + * of the allocation will be increased until the start address is aligned correctly, in creating + * an (`align' - 1) bytes sized memory hole in the worst case. The allocated memory will be + * zeroed by the allocator. + * This allocator does not perform any error checking. If there are problems with this allocator, + * that means that the machine does not have enough memory to allocate the kernel page directory. + * Since paging was introduced with the Intel 486 and my first one had 4MB of memory, it's fair to + * say that this is unlikely to happen on any machine. + * + * You should not be using this function. If you find yourself using this allocator, you are almost + * certainly doing something wrong. + * + * RETURN VALUE + * The start address of the memory allocation + * + * ERRORS + * This function does not return errors. + */ static void* _phys_alloc(u32_t size, u32_t align) { extern u32_t _mem_start; @@ -88,6 +122,32 @@ static void* _phys_alloc(u32_t size, u32_t align) return(addr); } +/* + * pg_frame_alloc_start - Allocate a page frame from the start of the frame map + * + * SYNOPSIS + * void* pg_frame_alloc_start(void); + * + * DESCRIPTION + * The pg_frame_alloc_start() function attempts to allocate a page frame (i.e. a physical + * page) from the start of the frame map. The frame map is a global structure that tracks + * the availability of every 4KB page frame in the machine. Simply speaking, the first bit + * in the frame map represents the page frame at address 0x0, the second bit represents the + * page frame at address 0x1000, and so on. + * What this function does is, get the first zero bit in the frame map, set the bit, and + * return the address of the page frame. + * + * This function is used exclusively to allocate heap space for the kernel. It should never + * be called directly, except from the code that is responsible for the kernel heap. For + * page frame allocations for processes, pg_frame_alloc_end() must be used instead. + * + * RETURN VALUE + * On success, the linear address of the newly allocated page frame is returned. In the case + * of an error, NULL will be returned. + * + * ERRORS + * This function does not return additional information about error conditions. + */ void* pg_frame_alloc_start(void) { u32_t frm; @@ -112,6 +172,28 @@ void* pg_frame_alloc_start(void) return(NULL); } +/* + * pg_frame_alloc_end - Allocate a page frame from the end of the frame map + * + * SYNOPSIS + * void* pg_frame_alloc_end(void); + * + * DESCRIPTION + * The pg_frame_alloc_end() function attempts to allocate a page frame (i.e. a physical + * page) from the end of the frame map. This function works essentially the same way as + * pg_frame_alloc_start(), except that it scans the frame map backwards. + * This function is intended to allocate page frames for processes. This function should + * be used exclusively from code that is managing the page directories, page tables, and + * page allocations of processes. For page frame allocations for the kernel heap, the + * pg_frame_alloc_start() function must be used instead. + * + * RETURN VALUE + * On success, the linear address of the newly allocated page frame is returned. In the case + * of an error, NULL will be returned. + * + * ERRORS + * This function does not return additional information about error conditions. + */ void* pg_frame_alloc_end(void) { u32_t frm; @@ -134,6 +216,33 @@ void* pg_frame_alloc_end(void) return(NULL); } +/* + * pg_frame_free() - Release a page frame + * + * SYNOPSIS + * void pg_frame_free(void *addr); + * + * DESCRIPTION + * The pg_frame_free() function releases the page frame that corresponds to the address + * passed in `addr'. This function clears the respective bit in the frame map, so that + * it may be allocated for other purposes. The position in the frame map is determined + * by means of a simple division, which means that any address that points into the frame + * may be passed to this function in order to free the frame. For example, passing any + * address in [0, 0x1000) will cause the first page frame to be released. + * This function may be used to release page frames obtained through either of the + * pg_frame_alloc_start() and pg_frame_alloc_end() functions. + * + * This function does not perform any error checking. The caller is responsible not to + * pass any addresses that cause array accesses outside of the frame map. In other words, + * care should be taken not to pass values other than those obtained through either of the + * allocation functions. + * + * RETURN VALUE + * void + * + * ERRORS + * This function does not signal any errors. + */ void pg_frame_free(void *addr) { _frame_clear((u32_t)addr); -- 2.47.3