Skip to content

Commit

Permalink
Merge pull request #23 from ianchen-tw/lab3-startup-allocator
Browse files Browse the repository at this point in the history
Lab3 startup allocator
  • Loading branch information
ianchen-tw committed Apr 5, 2021
2 parents 4e5c953 + 1706166 commit c7f4fa7
Show file tree
Hide file tree
Showing 15 changed files with 565 additions and 85 deletions.
3 changes: 2 additions & 1 deletion Makefile
Expand Up @@ -121,7 +121,8 @@ endef

# Start qemu with tty opend on host, waiting for gdb to connect
define DEBUG_KERNEL
$(_run_qemu_mux_base) \
$(_run_qemu_base) \
-serial null -serial stdio \
-s -S \
-kernel
endef
15 changes: 14 additions & 1 deletion impl-c/include/cfg.h
@@ -1,3 +1,16 @@
#pragma once

#define CFG_LOG_ENABLE 0
/**
* Log
* */

#define CFG_LOG_ENABLE 0
#define CFG_LOG_STARTUP
#define CFG_LOG_KALLOC

/**
* TEST
* */
#define CFG_RUN_TEST
// memory management
#define CFG_RUN_STATUP_ALLOC_TEST
41 changes: 41 additions & 0 deletions impl-c/include/mm.h
@@ -0,0 +1,41 @@
#pragma once

#include "list.h"
#include "mm/alloc.h"
#include "mm/const.h"
#include "mm/frame.h"
#include "mm/startup.h"
#include <stdint.h>

/**
* Allocation Manager:
* On charge of dynamic memory allocation by using frame/object allocators
*
* Caution: must initialize the startup allocator before using
* any of the function listed below, otherwise the buddy system
* wont initialize properly
* */

extern struct AllocationManager KAllocManager;
typedef struct AllocationManager {
SlabAllocator obj_allocator_list[SLAB_NUM_SLAB_SIZES];
BuddyAllocater frame_allocator;
} AllocationManager;

// Statically linked to the heap space
// because their lifetimes is equal to the system itself
extern struct Frame Frames[BUDDY_MAX_EXPONENT << 1];

// Allocate a memory space to use in kernel space
void *kalloc(int size);

// Free a memory space
void kfree(void *addr);

// Initialize dynamic memory allocator
void KAllocManager_init();

void KAllocManager_show_status();

// Run several allocation/free as an example
void KAllocManager_run_example();
48 changes: 6 additions & 42 deletions impl-c/include/mem.h → impl-c/include/mm/alloc.h
@@ -1,31 +1,11 @@
#pragma once

#include "list.h"
#include "mm/const.h"
#include "mm/frame.h"
#include "mm/startup.h"
#include <stdint.h>

// #define BUDDY_MAX_EXPONENT 17 // 512Mb
#define BUDDY_MAX_EXPONENT 10
#define FRAME_SHIFT 14 // 4Kb

#define BUDDY_NUM_FREE_LISTS (BUDDY_MAX_EXPONENT + 1)

#define MEMORY_START 0x90000

// SlabAllocator
// manage slabs with the same allocation size,
// A slab is a frame allocated with small objects with same size
// + @SLAB_MAX_SLOTS: The number of pages available for a single slab
// -> Frame is 4kb by architecture.
// CortexA53 is 16 bytes aligned, so the here 16 bytes is set to be
// the minimum size available for objects in slab.
// -> Therefore, the maximum slots in slab is 4096/16 = 256
#define SLAB_MAX_SLOTS 256

// The size of slab range from 16(2^4) to 512(2^9) bytes
#define SLAB_OBJ_MIN_SIZE_EXP 4
#define SLAB_OBJ_MAX_SIZE_EXP 9
#define SLAB_NUM_SLAB_SIZES 6

typedef struct Frame {
// inherit a list type, so we could cast FrameNode into list_head
struct list_head list_base;
Expand All @@ -44,6 +24,7 @@ typedef struct Frame {
// allocate contiguous frames
typedef struct BuddyAllocater {
list_head_t free_lists[BUDDY_NUM_FREE_LISTS];
struct Frame *frames;
} BuddyAllocater;

typedef struct SlabAllocator {
Expand All @@ -59,31 +40,14 @@ typedef struct SlabAllocator {
// full_list for storage.
} SlabAllocator;

typedef struct AllocationManager {
SlabAllocator obj_allocator_list[SLAB_NUM_SLAB_SIZES];
BuddyAllocater frame_allocator;
} AllocationManager;

void *kalloc(int size);
void kfree(void *addr);

// Initialize dynamic memory allocator
void KAllocManager_init();

void KAllocManager_show_status();

// Statically linked to the heap space
// because their lifetimes is equal to the system itself
struct Frame Frames[BUDDY_MAX_EXPONENT << 1];
struct AllocationManager KAllocManager;

// Call slab allocator for allocate an object
void *slab_alloc(SlabAllocator *alloc);

// Free an object
void slab_free(void *obj);

void buddy_init(BuddyAllocater *alloc);
void buddy_init(BuddyAllocater *alloc, StartupAllocator_t *sa,
struct Frame *frames);
struct Frame *buddy_alloc(BuddyAllocater *alloc, int size_in_byte);
void buddy_free(BuddyAllocater *alloc, struct Frame *frame);
void buddy_dump(BuddyAllocater *alloc);
26 changes: 26 additions & 0 deletions impl-c/include/mm/const.h
@@ -0,0 +1,26 @@
#pragma once

#define SLAB_NUM_SLAB_SIZES 6

#define BUDDY_MAX_EXPONENT 18 // 1GB
// #define BUDDY_MAX_EXPONENT 10
// #define BUDDY_MAX_EXPONENT 5

#define BUDDY_NUM_FREE_LISTS (BUDDY_MAX_EXPONENT + 1)

// #define MEMORY_START 0x90000
#define MEMORY_START 0x0

// SlabAllocator
// manage slabs with the same allocation size,
// A slab is a frame allocated with small objects with same size
// + @SLAB_MAX_SLOTS: The number of pages available for a single slab
// -> Frame is 4kb by architecture.
// CortexA53 is 16 bytes aligned, so the here 16 bytes is set to be
// the minimum size available for objects in slab.
// -> Therefore, the maximum slots in slab is 4096/16 = 256
#define SLAB_MAX_SLOTS 256

// The size of slab range from 16(2^4) to 512(2^9) bytes
#define SLAB_OBJ_MIN_SIZE_EXP 4
#define SLAB_OBJ_MAX_SIZE_EXP 9
3 changes: 3 additions & 0 deletions impl-c/include/mm/frame.h
@@ -0,0 +1,3 @@
#pragma once
#define FRAME_SHIFT 12 // 4Kb
#define FRAME_ADDR_BASE (1 << FRAME_SHIFT)
47 changes: 47 additions & 0 deletions impl-c/include/mm/startup.h
@@ -0,0 +1,47 @@
#pragma once
#include "bool.h"
#include "cfg.h"
#include "test.h"

#define STARTUP_MAX_RESERVE_COUNT 10

/**
* Startup allocator:
* The very first memory allocator of the opoerating system
*
* The purpose of startup allocator is to reserve spaces on system starup,
* Hand all of it's knowledfe to( memory regions have bee reserved)
* to the dynamic memory allcator.
*
* This allocator is fairly basic, which only allocate but not free spaces at
* all.
*
* */

typedef struct MemRegion {
void *addr;
unsigned long size;
} MemRegion;

typedef struct StartupAllocator {
int num_reserved;
int max_reserved;
struct MemRegion *_reserved;
} StartupAllocator_t;

extern struct MemRegion ReservedRegions[STARTUP_MAX_RESERVE_COUNT];
extern StartupAllocator_t StartupAlloc;

bool is_overlap(MemRegion *a1, MemRegion *a2);

// Public api: Initialize the starup allocator module
void startup_init();

// Request StartupAllocator to allocate a space
// void *startup_alloc(unsigned long size);

// Reqeust StartupAllocator to reserve an area
bool startup_reserve(void *addr, unsigned long size);

// Only used for running tests
void test_startup_alloc();
33 changes: 33 additions & 0 deletions impl-c/include/test.h
@@ -0,0 +1,33 @@
#pragma once

#include "bool.h"
#include "uart.h"

#define TEST_FAILED(name, description) \
{ uart_println("\033[0;31m[TEST][ERR] %s: %s\033[0m", name, description); }

#define TEST_SUCCESS(name, description) \
{ uart_println("\033[0;32m[TEST][OK] %s: %s\033[0m", name, description); }

#define TEST1(test, name, desc) \
{ \
if (test() == true) { \
TEST_SUCCESS(name, desc); \
} else { \
TEST_FAILED(name, desc); \
} \
}

static inline void unittest(int (*f)(), char *s, char *de) { TEST1(f, s, de); }

// Return false once the condition does not meet
#define assert(cond) \
{ \
if (!(cond)) { \
return false; \
} \
}

void run_tests();

void test_suite_startup_alloc();
3 changes: 3 additions & 0 deletions impl-c/kernel/linker.ld
Expand Up @@ -7,6 +7,7 @@ SECTIONS
for more information
*/
. = 0x80000;
__kernel_start = .;
.text :
{
KEEP(*(.text.boot)) *(.text)
Expand All @@ -25,6 +26,8 @@ SECTIONS
*(.bss .bss.*)
__bss_end = .;
}
. = ALIGN(4096);
__kernel_end = .;
_end = .;
}
__bss_size = (__bss_end - __bss_start) >> 3;
Expand Down
46 changes: 24 additions & 22 deletions impl-c/kernel/main.c
@@ -1,38 +1,40 @@
#include "mem.h"
#include "cfg.h"
#include "mm.h"
#include "mm/startup.h"
#include "shell.h"
#include "test.h"
#include "uart.h"

extern unsigned char __kernel_start, __kernel_end;

int main() {
uart_init();
uart_println("uart initialized");

#ifdef CFG_RUN_TEST
run_tests();
#endif

startup_init();

// Kernel
startup_reserve((void *)0x0, 0x1000); // spin table
startup_reserve((void *)0x60000, 0x20000); // stack
startup_reserve((void *)(&__kernel_start),
(&__kernel_end - &__kernel_start)); // kernel
// startup_reserve((void *)(&kn_end), mem_size / PAGE_SIZE); // buddy
// System
startup_reserve((void *)0x3f000000, 0x1000000); // MMIO

KAllocManager_init();
KAllocManager_run_example();
// KAllocManager_show_status();

uart_println("-------------------------------");
uart_println(" Operating System Capstone 2021");
uart_println("-------------------------------");

void *a[30];
for (int i = 0; i < 5; i++) {
a[i] = kalloc(8192);
uart_println("i:%d, a: %x", i, a[i]);
}

for (int i = 0; i < 5; i++) {
kfree(a[i]);
}

for (int i = 0; i < 5; i++) {
a[i] = kalloc(13);
uart_println("i:%d, a: %x", i, a[i]);
};
if (a[0] == a[1]) {
uart_println("nooo");
}
for (int i = 0; i < 5; i++) {
kfree(a[i]);
}
uart_println(" input filename to see file content");

while (1) {
shellPrintPrompt();
shellInputLine();
Expand Down
5 changes: 5 additions & 0 deletions impl-c/kernel/test.c
@@ -0,0 +1,5 @@
#include "test.h"
#include "cfg.h"
#include "mm/startup.h"

void run_tests() { test_startup_alloc(); }

0 comments on commit c7f4fa7

Please sign in to comment.