Implement kernel memory allocator (kmalloc/kfree) and freestanding string library (AI)

- Added first-fit free-list allocator with block splitting and coalescing.
  Provides kmalloc(), kfree(), and kcalloc() for kernel-space dynamic memory.
- Each block carries an inline header with a magic value (0xCAFEBABE) for
  heap corruption detection, plus double-free checking.
- Memory is obtained from the paging subsystem in 4 KiB page increments.
  All allocations are 8-byte aligned with a 16-byte minimum block size.
- Created freestanding string.c with memset, memcpy, memmove, memcmp,
  strlen, strcmp, strncmp, strcpy, strncpy — replacing the unavailable
  libc implementations.
- Added documentation in docs/kmalloc.md.

Tested: kmalloc(64) returns 0xD0001010 (in kernel heap) and kfree succeeds.
Works with both 4 MiB and 128 MiB RAM.
This commit is contained in:
AI
2026-02-23 11:06:52 +00:00
parent fb61ab7c15
commit f63cd9eb3f
7 changed files with 551 additions and 1 deletions

61
docs/kmalloc.md Normal file
View File

@@ -0,0 +1,61 @@
# Kernel Memory Allocator (kmalloc)
## Overview
The kernel memory allocator provides `kmalloc()` and `kfree()` for dynamic memory allocation within the kernel. It uses the paging subsystem to obtain physical memory on demand.
## Architecture
### Free-List Allocator
The allocator maintains a singly-linked free list of available memory blocks, ordered by address. Each block carries an inline header:
```c
typedef struct block_header {
uint32_t size; // Usable bytes (excludes header)
uint32_t magic; // 0xCAFEBABE for integrity checking
struct block_header *next; // Next free block (free list only)
uint8_t is_free; // 1 = free, 0 = allocated
} block_header_t;
```
### Allocation Strategy
1. **First-fit search:** Walk the free list for the first block with `size >= requested`.
2. **Block splitting:** If the found block is significantly larger than needed, it is split into the allocated portion and a new free block.
3. **Page expansion:** If no suitable block exists, a new 4 KiB page is obtained from `paging_alloc_page()`.
All allocations are 8-byte aligned. Minimum block size is 16 bytes to limit fragmentation.
### Deallocation
1. The block header is located by subtracting `sizeof(block_header_t)` from the user pointer.
2. The block's magic number is verified to detect corruption.
3. The block is inserted back into the free list in address order.
4. **Coalescing:** Adjacent free blocks are merged to reduce fragmentation.
### Integrity Checks
- A magic value (`0xCAFEBABE`) in each block header detects heap corruption.
- Double-free is detected by checking the `is_free` flag.
## API
```c
void init_kmalloc(void);
void *kmalloc(size_t size);
void kfree(void *ptr);
void *kcalloc(size_t count, size_t size);
```
## Key Files
- `src/kmalloc.c` / `src/kmalloc.h` — Allocator implementation.
- `src/string.c` — Freestanding `memset`, `memcpy`, `strlen`, etc.
- `src/paging.c` — Provides physical page backing.
## Limitations
- Maximum single allocation is ~4080 bytes (one page minus header).
- No multi-page allocations for large objects.
- Free virtual addresses are not reused after `paging_free_page()`.