Assignment 4 p1 completed
This commit is contained in:
164
notes/work-summary-2026-04-14.md
Normal file
164
notes/work-summary-2026-04-14.md
Normal 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**
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
|
||||
26
src/OSDev_18/include/kernel/memory.h
Normal file
26
src/OSDev_18/include/kernel/memory.h
Normal 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
|
||||
@@ -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
161
src/OSDev_18/src/malloc.c
Normal 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
44
src/OSDev_18/src/memory.c
Normal 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");
|
||||
}
|
||||
44
src/OSDev_18/src/memutils.c
Normal file
44
src/OSDev_18/src/memutils.c
Normal 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;
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user