Assignment 4 p1 completed

This commit is contained in:
Teodor
2026-04-14 21:33:21 +00:00
parent cad047a927
commit 9d6c378ac7
8 changed files with 483 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
# Assignment 4 Part 1: Memory Management
## Overview
In this part of the assignment, a basic memory management system was implemented for a simple OS kernel. The goal was to initialize kernel memory, enable paging, and implement dynamic memory allocation using `malloc()` and `free()`.
---
## Implemented Features
### Kernel Memory Initialization
- Used:
```c
extern uint32_t end;
```
to get the end address of the kernel from the linker.
- Implemented:
```c
init_kernel_memory(&end);
```
- Set up:
- `heap_begin`
- `heap_end`
- `pheap_begin` (page-aligned heap)
- `pheap_end`
---
### Paging
- Implemented:
```c
init_paging();
```
- Set up:
- Page directory at `0x400000`
- Page tables starting at `0x404000`
- Identity-mapped:
- `0x00000000 → 0x00000000`
- `0x400000 → 0x400000`
- Enabled paging by modifying `cr0` and `cr3`.
---
### Dynamic Memory Allocation
#### malloc()
- Implemented a simple heap allocator.
- Stores metadata using:
```c
typedef struct {
uint8_t status;
uint32_t size;
} alloc_t;
```
- Supports:
- Sequential allocation
- Reuse of freed blocks
- Zeroes allocated memory using `memset`.
---
#### free()
- Frees memory by marking the block as unused.
- Prevents errors by:
```c
if (!mem) return;
```
- Correctly updates `memory_used`.
---
#### Block Reuse
- When a block is freed, it can be reused by future `malloc()` calls.
- Verified by:
- Freeing a block
- Allocating a smaller block
- Observing same address reused
---
### Page-Aligned Allocation (pmalloc)
- Implemented `pmalloc()` and `pfree()`:
- Allocates memory in 4KB pages
- Uses a descriptor array (`pheap_desc`)
- Located in upper memory region near `0x400000`
---
### Memory Utility Functions
Implemented:
- `memcpy()`
- `memset()`
- `memset16()`
These replace standard library functions in kernel space.
---
### Debug Output
#### Memory Layout
- Implemented:
```c
print_memory_layout();
```
- Displays:
- Memory used
- Memory free
- Heap size
- Heap start/end
- Page heap start/end
#### Allocation Logs
- Outputs allocation details:
```
Allocated X bytes from 0x... to 0x...
Re-allocated X bytes from 0x... to 0x...
```
---
### Hex Output for Addresses
- Implemented:
```c
TerminalWriteHex(uint32_t num);
```
- Ensures correct formatting of memory addresses (base 16)
- Avoids confusion from decimal output
---
## Testing & Verification
### Allocation Test
```c
void* memory1 = malloc(48261);
void* memory2 = malloc(27261);
void* memory3 = malloc(12617);
```
### Free and Reuse Test
```c
free(memory2);
void* memory4 = malloc(1000);
```
### Result
- `memory4` reused the same address as `memory2`
- Confirms:
- `free()` works
- allocator reuses memory correctly
---
## Conclusion
- Successfully implemented a basic kernel memory manager
- Paging is enabled and functioning
- `malloc()` and `free()` work correctly
- Memory reuse is verified
- Debug output is clear and correctly formatted
---
## Next Step
Proceed to **Part 2: PIT and Sleep Functions**

View File

@@ -67,6 +67,9 @@ add_executable(uiaos-kernel
src/interrupt.c
src/interrupt.asm
src/keyboard.c
src/malloc.c
src/memutils.c
src/memory.c
)

View File

@@ -0,0 +1,26 @@
#ifndef KERNEL_MEMORY_H
#define KERNEL_MEMORY_H
#include <libc/stdint.h>
typedef struct {
uint8_t status;
uint32_t size;
} alloc_t;
void init_kernel_memory(uint32_t* kernel_end);
void init_paging(void);
void paging_map_virtual_to_phys(uint32_t virt, uint32_t phys);
char* pmalloc(size_t size);
void* malloc(size_t size);
void free(void *mem);
void* memcpy(void* dest, const void* src, size_t num);
void* memset (void* ptr, int value, size_t num);
void* memset16 (void* ptr, uint16_t value, size_t num);
void print_memory_layout(void);
#endif

View File

@@ -4,6 +4,9 @@
#include <kernel/idt.h>
#include <kernel/interrupt.h>
#include <kernel/keyboard.h>
#include <kernel/memory.h>
extern uint32_t end;
void main(void) {
TerminalInitialize();
@@ -12,6 +15,34 @@ void main(void) {
RegisterInterruptHandler(IRQ1, KeyboardHandler);
init_kernel_memory(&end);
init_paging();
print_memory_layout();
void* memory1 = malloc(48261);
void* memory2 = malloc(27261);
void* memory3 = malloc(12617);
TerminalWriteString("memory1 = ");
TerminalWriteHex((uint32_t)memory1);
TerminalWriteString("\n");
TerminalWriteString("memory2 = ");
TerminalWriteHex((uint32_t)memory2);
TerminalWriteString("\n");
TerminalWriteString("memory3 = ");
TerminalWriteHex((uint32_t)memory3);
TerminalWriteString("\n");
free(memory2);
void* memory4 = malloc(1000);
TerminalWriteString("memory4 = ");
TerminalWriteHex((uint32_t)memory4);
TerminalWriteString("\n");
for (;;) {
__asm__ volatile("hlt");
}

161
src/OSDev_18/src/malloc.c Normal file
View File

@@ -0,0 +1,161 @@
#include <kernel/memory.h>
#include <kernel/terminal.h>
#include <libc/stdint.h>
#define MAX_PAGE_ALIGNED_ALLOCS 32
static uint32_t last_alloc = 0;
static uint32_t heap_end = 0;
static uint32_t heap_begin = 0;
static uint32_t pheap_begin = 0;
static uint32_t pheap_end = 0;
static uint8_t *pheap_desc = 0;
static uint32_t memory_used = 0;
void init_kernel_memory(uint32_t* kernel_end) {
uint32_t kernelEndAddr = (uint32_t)kernel_end;
last_alloc = kernelEndAddr + 0x1000;
heap_begin = last_alloc;
pheap_end = 0x400000;
pheap_begin = pheap_end - (MAX_PAGE_ALIGNED_ALLOCS * 4096);
heap_end = pheap_begin;
memset((char*)heap_begin, 0, heap_end - heap_begin);
pheap_desc = (uint8_t *)malloc(MAX_PAGE_ALIGNED_ALLOCS);
TerminalWriteString("Kernel heap starts at 0x");
TerminalWriteUInt(last_alloc);
TerminalWriteString("\n");
}
void print_memory_layout(void) {
TerminalWriteString("Memory used:");
TerminalWriteUInt(memory_used);
TerminalWriteString(" bytes\n");
TerminalWriteString("Memory free:");
TerminalWriteUInt(heap_end - heap_begin - memory_used);
TerminalWriteString(" bytes\n");
TerminalWriteString("Heap size:");
TerminalWriteUInt(heap_end - heap_begin);
TerminalWriteString(" bytes\n");
TerminalWriteString("Heap start: ");
TerminalWriteHex(heap_begin);
TerminalWriteString("\n");
TerminalWriteString("Heap end: ");
TerminalWriteHex(heap_end);
TerminalWriteString("\n");
TerminalWriteString("PHeap start: ");
TerminalWriteHex(pheap_begin);
TerminalWriteString("\n");
TerminalWriteString("PHeap end: ");
TerminalWriteHex(pheap_end);
TerminalWriteString("\n");
}
void free(void *mem) {
if (!mem) return;
alloc_t* alloc = (alloc_t*)((uint8_t*)mem - sizeof(alloc_t));
if (alloc->status) {
memory_used -= alloc->size + sizeof(alloc_t) + 4;
alloc->status = 0;
}
}
void pfree(void *mem) {
uint32_t addr = (uint32_t)mem;
if (addr < pheap_begin || addr >= pheap_end) return;
addr -= pheap_begin;
addr /= 4096;
pheap_desc[addr] = 0;
}
char* pmalloc(size_t size) {
(void) size;
for (int i = 0; i < MAX_PAGE_ALIGNED_ALLOCS; i++) {
if (pheap_desc[i]) continue;
pheap_desc[i] = 1;
TerminalWriteString("PAllocated from 0x");
TerminalWriteUInt(pheap_begin + i * 4096);
TerminalWriteString(" to 0x");
TerminalWriteUInt(pheap_begin + (i+1) * 4096);
TerminalWriteString("\n");
return (char*)(pheap_begin + i * 4096);
}
TerminalWriteString("pmalloc: FATAL: failure!\n");
return 0;
}
void* malloc(size_t size) {
if(!size) return 0;
uint8_t* mem = (uint8_t*)heap_begin;
while ((uint32_t)mem < last_alloc) {
alloc_t* a = (alloc_t*)mem;
if(!a->size) goto nalloc;
if(a->status) {
mem += sizeof(alloc_t) + a->size + 4;
continue;
}
if(a->size >= size) {
a->status = 1;
memset(mem + sizeof(alloc_t), 0, size);
memory_used += a->size + sizeof(alloc_t) + 4;
TerminalWriteString("Re-allocated ");
TerminalWriteUInt(size);
TerminalWriteString(" bytes from 0x");
TerminalWriteUInt((uint32_t)(mem + sizeof(alloc_t)));
TerminalWriteString(" to 0x");
TerminalWriteUInt((uint32_t)(mem + sizeof(alloc_t) + size));
TerminalWriteString("\n");
return (char*)(mem + sizeof(alloc_t));
}
mem += a->size + sizeof(alloc_t) + 4;
}
nalloc:;
if (last_alloc + size + sizeof(alloc_t) + 4 >= heap_end) {
TerminalWriteString("Cannot allocate bytes! Out of memory.\n");
for (;;) {
__asm__ volatile("hlt");
}
}
alloc_t* alloc = (alloc_t*)last_alloc;
alloc->status = 1;
alloc->size = size;
last_alloc += size + sizeof(alloc_t) + 4;
memory_used += size + 4 + sizeof(alloc_t);
memset((char *)((uint32_t)alloc + sizeof(alloc_t)), 0, size);
TerminalWriteString("Allocated ");
TerminalWriteUInt(size);
TerminalWriteString(" bytes from 0x");
TerminalWriteUInt((uint32_t)alloc + sizeof(alloc_t));
TerminalWriteString(" to 0x");
TerminalWriteUInt(last_alloc);
TerminalWriteString("\n");
return (char*)((uint32_t)alloc + sizeof(alloc_t));
}

44
src/OSDev_18/src/memory.c Normal file
View File

@@ -0,0 +1,44 @@
#include <kernel/memory.h>
#include <kernel/terminal.h>
#include <libc/stdint.h>
static uint32_t* page_directory = 0;
static uint32_t page_dir_loc = 0;
static uint32_t* last_page = 0;
void paging_map_virtual_to_phys(uint32_t virt, uint32_t phys) {
uint16_t id = virt >> 22;
for(int i = 0; i < 1024; i++) {
last_page[i] = phys | 3;
phys += 4096;
}
page_directory[id] = ((uint32_t)last_page) | 3;
last_page = (uint32_t*)(((uint32_t)last_page) + 4096);
}
void paging_enable() {
asm volatile("mov %%eax, %%cr3": :"a"(page_dir_loc));
asm volatile("mov %cr0, %eax");
asm volatile("orl $0x80000000, %eax");
asm volatile("mov %eax, %cr0");
}
void init_paging(void) {
TerminalWriteString("Setting up paging\n");
page_directory = (uint32_t*)0x400000;
page_dir_loc = (uint32_t)page_directory;
last_page = (uint32_t*)0x404000;
for(int i = 0; i < 1024; i++) {
page_directory[i] = 0 | 2;
}
paging_map_virtual_to_phys(0, 0);
paging_map_virtual_to_phys(0x400000, 0x400000);
paging_enable();
TerminalWriteString("Paging was successfully enabled!\n");
}

View File

@@ -0,0 +1,44 @@
#include <kernel/memory.h>
#include <libc/stdint.h>
void* memcpy(void* dest, const void* src, size_t count ) {
char* dst8 = (char*)dest;
char* src8 = (char*)src;
if (count & 1) {
dst8[0] = src8[0];
dst8 += 1;
src8 += 1;
}
count /= 2;
while (count--) {
dst8[0] = src8[0];
dst8[1] = src8[1];
dst8 += 2;
src8 += 2;
}
return dest;
}
void* memset16 (void* ptr, uint16_t value, size_t num) {
uint16_t* p = ptr;
while(num--) {
*p++ = value;
}
return ptr;
}
void* memset (void* ptr, int value, size_t num ) {
unsigned char* p = ptr;
while(num--) {
*p++ = (unsigned char)value;
}
return ptr;
}

View File

@@ -116,3 +116,13 @@ void TerminalWriteUInt(uint32_t num) {
}
}
void TerminalWriteHex(uint32_t num) {
TerminalWriteString("0x");
char hexChars[] = "0123456789ABCDEF";
for (int i = 28; i >= 0; i -= 4) {
uint8_t digit = (num >> i) & 0xF;
TerminalPutChar(hexChars[digit]);
}
}