Compare commits

...

18 commits

Author SHA1 Message Date
Maxime Bloch fe30349d17
Fix ifndef names. Remove useless summation 2020-01-29 22:53:38 +01:00
Maxime Bloch 256efe6b22
add clion files to gitignore 2020-01-29 05:39:43 +01:00
Maxime Bloch 5b8f5cac54
Add page alignment 2020-01-29 05:32:50 +01:00
Maxime Bloch 8ae1816819
check of memory management in readme 2020-01-29 04:41:40 +01:00
Maxime Bloch a537ac162e
Remove unneeded define 2020-01-29 04:32:10 +01:00
Maxime Bloch 3af5ab06a7
Add 2 column printing for more space efficiency. 2020-01-29 04:31:44 +01:00
Maxime Bloch c66bb87aaf
Remove old search function 2020-01-29 03:57:24 +01:00
Maxime Bloch 200e58b6f6
Remove kernel prints, it's to much. Add simple text save function 2020-01-28 23:24:51 +01:00
Maxime Bloch 9589e2f804
Merge branch 'memory_allocation' of github.com:ZeusWPI/TABS into memory_allocation 2020-01-28 23:11:39 +01:00
Maxime Bloch 5e1a12239a
Refactor to use the print function, add byte formatter, at memdump cmd 2020-01-28 23:11:11 +01:00
Maxime Bloch 5c8f8defe0
Refactor to use the print function, at byte formatter, at memdump cmd 2020-01-28 23:10:35 +01:00
Maxime Bloch 831b49d8dd
Uncomment and update empty mem page prints 2020-01-28 22:35:25 +01:00
Maxime Bloch 2064d1a802
Edit comment 2020-01-28 22:33:11 +01:00
Maxime Bloch d547432270
Maybe include the file I want to commit 2020-01-28 22:32:32 +01:00
Maxime Bloch a042169845
Add print function, add more memory prints at startup 2020-01-28 22:25:37 +01:00
Maxime Bloch 4f214b2d5a
Add printing on terminal. Add some usage on boot. 2020-01-28 18:54:42 +01:00
Maxime Bloch fafe06ed2b
Refactor to holding linked list data before the alloced blocks.
These "tags" hold the pointers between the alloced blocks.
2020-01-28 18:04:46 +01:00
Maxime Bloch ea9f4c6e49
Working linked memory structure on linux. 2020-01-28 04:18:03 +01:00
8 changed files with 487 additions and 97 deletions

4
.gitignore vendored
View file

@ -1 +1,5 @@
target/
.idea/
CMakeLists.txt
cmake-build-debug/

View file

@ -37,7 +37,7 @@ The kernel is based on [the bare bones kernel from the OSDev wiki](https://wiki.
- [ ] Write files in directory
- [ ] Tests
- [ ] Running executables from filesystem
- [ ] Better memory management
- [x] Better memory management
- [ ] Better shell
As a test, I've implemented day 1 of [advent of code](https://adventofcode.com/) on the [AoC branch](https://github.com/Robbe7730/RoBoot/tree/AoC).

View file

@ -290,7 +290,7 @@ repnz movsd
or ax, ax
jnz .elf_ph_loop
.start_kernel
.start_kernel:
cmp edi, KERNEL_START
je .invalid_elf

View file

@ -2,7 +2,7 @@
#if defined(__linux__)
#error "You are not using a cross-compiler, you will most certainly run into trouble"
#endif
/* This tutorial will only work for the 32-bit ix86 targets. */
#if !defined(__i386__)
#error "This kernel needs to be compiled with a ix86-elf compiler"
@ -16,52 +16,67 @@
#include "memory.c"
#include "interrupts.c"
#include "shell.c"
#include "util/printer.c"
static inline bool are_interrupts_enabled() {
unsigned long flags;
asm volatile ( "pushf\n\t"
"pop %0"
: "=g"(flags) );
: "=g"(flags));
return flags & (1 << 9);
}
void kernel_main(void)
{
/* Initialize terminal interface */
terminal_initialize();
void kernel_main(void) {
/* Initialize terminal interface */
terminal_initialize();
terminal_putchar('H');
terminal_putchar('e');
terminal_putchar('l');
terminal_putchar('l');
terminal_putchar('o');
terminal_putchar('H');
terminal_putchar('e');
terminal_putchar('l');
terminal_putchar('l');
terminal_putchar('o');
terminal_setcolor(vga_entry_color(VGA_COLOR_GREEN, VGA_COLOR_BLACK));
terminal_writestring(" kernel");
print(" kernel");
terminal_setcolor(vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
terminal_writestring(" World!\n");
terminal_writestring("Newlines!\n");
print(" World!\n");
print("Newlines!\n");
char* memory_str = alloc(sizeof(char) * 7);
for (int i = 0; i < 6; i++) {
memory_str[i] = "Memory"[i];
}
memory_str[6] = 0;
char *memory_str = alloc(sizeof(char) * 7);
for (int i = 0; i < 6; i++) {
memory_str[i] = "Memory"[i];
}
memory_str[6] = 0;
char* management_str = alloc(sizeof(char) * 13);
for (int i = 0; i < 13; i++) {
management_str[i] = " management!\n"[i];
}
management_str[13] = 0;
char *management_str = alloc(sizeof(char) * 13);
for (int i = 0; i < 13; i++) {
management_str[i] = " management!\n"[i];
}
management_str[13] = 0;
terminal_writestring(memory_str);
terminal_writestring(management_str);
print(memory_str);
print(management_str);
terminal_writestring((are_interrupts_enabled())? "Interrupts!\n": "No interrupts :(\n");
free(memory_str);
free(management_str);
interrupt_init();
// Some dummy allocations to demonstrate the states of memory and to showcase the memory dump printout.
void* ptr = alloc(30);
alloc(30);
alloc(31);
free(ptr);
for(;;) {
shell_step();
}
void* ptr2 = alloc(64);
alloc(61);
free(ptr2);
print((are_interrupts_enabled()) ? "Interrupts!\n" : "No interrupts :(\n");
interrupt_init();
print_memory();
for (;;) {
shell_step();
}
}

View file

@ -1,13 +1,208 @@
#ifndef MEMORY_C
#define MEMORY_C
#include <stddef.h>
void* _curr_end = (void*) 0x200000;
#include "terminal.c"
#include "util/printer.c"
void* alloc(size_t size) {
void* thanks_jp = _curr_end;
_curr_end += size;
return thanks_jp;
#define MEMORY_START 0x200000
//#define MEMORY_END 0x300000
#define PAGE_ALIGNMENT 4
//size_t total_memory = MEMORY_END - MEMORY_START;
typedef struct page_tag {
size_t size;
size_t realsize;
struct page_tag *prev;
struct page_tag *next;
} page_tag;
page_tag *start = (void *) MEMORY_START;;
size_t calculate_realsize(size_t size) {
if (size % PAGE_ALIGNMENT == 0) return size;
return size + PAGE_ALIGNMENT - (size % PAGE_ALIGNMENT);
}
#endif // MEMORY_C
void *alloc(size_t size) {
page_tag *curr_page = start;
while (curr_page->next != NULL) {
page_tag *new_page = ((void *) curr_page) + sizeof(page_tag) + curr_page->realsize;
size_t realsize = calculate_realsize(size);
if ((void *) new_page + sizeof(page_tag) + realsize <= (void *) curr_page->next) {
new_page->size = size;
new_page->realsize = realsize;
curr_page->next->prev = new_page;
new_page->next = curr_page->next;
curr_page->next = new_page;
new_page->prev = curr_page;
return new_page + 1;
}
curr_page = curr_page->next;
}
page_tag *new_page = ((void *) curr_page) + sizeof(page_tag) + curr_page->realsize;
new_page->size = size;
new_page->realsize = calculate_realsize(size);
curr_page->next = new_page;
new_page->prev = curr_page;
new_page->next = NULL;
return new_page + 1;
}
void free(void *data) {
page_tag *data_tag = data - sizeof(page_tag);
data_tag->prev->next = data_tag->next;
data_tag->next->prev = data_tag->prev;
}
int amount_of_digits(int x) {
if (x == 0) return 1;
int n = 0;
while (x != 0) {
n += 1;
x /= 10;
}
return n;
}
#define MEM_SIZE_WIDTH 3
#define SPACED_ARRAY {' ', ' ', ' '};
void print_memory() {
print("____________________\n");
print(" === MEM DUMP === \n");
print("--------------------\n");
print("Page tag size: %d bytes\n", sizeof(page_tag));
print("Memory alignment: %d bytes\n", PAGE_ALIGNMENT);
print("=> idx: [page_tag_address] [data_address (size|aligment_padding_size)]\n\n");
page_tag *curr_page = start;
int i = 0;
bool left = true;
while (curr_page != NULL) {
char padding[MEM_SIZE_WIDTH] = SPACED_ARRAY;
padding[MEM_SIZE_WIDTH - amount_of_digits(curr_page->size)] = '\0';
print("%d: [%x] [%x (%s%d|%d)]",
i,
curr_page,
(curr_page + 1), padding, curr_page->size,
curr_page->realsize - curr_page->size);
if (left) {
print(" | ");
} else {
print("\n");
}
left = !left;
bool empty_print = false;
void *empty_start = (void *) curr_page + sizeof(page_tag) + curr_page->realsize;
if (empty_start + sizeof(page_tag) < (void *) curr_page->next) {
size_t memory_left = (void *) curr_page->next -
(empty_start + sizeof(page_tag));
char empty_padding[MEM_SIZE_WIDTH] = SPACED_ARRAY;
empty_padding[MEM_SIZE_WIDTH - amount_of_digits(memory_left)] = '\0';
print("_: free space (%d + %s%d| ) ",
sizeof(page_tag),
empty_padding,
memory_left
);
empty_print = true;
} else if (empty_start < (void *) curr_page->next) {
size_t memory_left = (void *) curr_page->next - empty_start;
char empty_padding[MEM_SIZE_WIDTH] = SPACED_ARRAY;
empty_padding[MEM_SIZE_WIDTH - amount_of_digits(memory_left)] = '\0';
print("_: not enough room (%s%d| ) ",
empty_padding,
memory_left);
empty_print = true;
}
if (empty_print) {
if (left) {
print(" | ");
} else {
print("\n");
}
left = !left;
}
curr_page = curr_page->next;
i += 1;
}
if (!left) {
print("\n");
}
print("____________________\n");
}
int command_mem_dump(char *string) {
print_memory();
}
//
//void test_allocs() {
// void *ptr0 = __alloc(64);
// void *ptr1 = __alloc(64);
// void *ptr4 = __alloc(64);
// print();
//
// printf("Free nr 2 -> %p\n", ptr1);
// __free(ptr1);
// print();
//
// printf("Alloc 32 bytes\n");
// void *ptr2 = __alloc(32);
// print();
//
// printf("Alloc 32 bytes\n");
// __alloc(32);
// print();
//
// printf("Alloc 8 bytes\n");
// void *ptr3 = __alloc(8);
// print();
//
// __free(ptr2);
// print();
// __free(ptr4);
// print();
// __free(ptr3);
// print();
//
// __free(ptr0);
// print();
//
// printf("#########\nTry almost fill\n");
// __alloc(160);
// print();
// __alloc(50);
// print();
//
//
//}
//
//int main() {
// start = malloc(sizeof(size_t) * 1000);
// start->next = NULL;
// start->prev = NULL;
// test_allocs();
//}
#endif // MEMORY_C

View file

@ -8,28 +8,29 @@
#include "terminal.c"
#include "inline_asm.c"
#include "drivers/keyboard/keyboard.c"
#include "memory.c"
char buffer[SHELL_CMD_BUFFER_SIZE];
int buffer_idx = 0;
int echo(char* input) {
int echo(char *input) {
terminal_writestring(input);
terminal_putchar('\n');
return 0;
}
int hello(char* unused) {
int hello(char *unused) {
terminal_writestring("Hello, world!\n");
return 0;
}
int cls(char* unused) {
int cls(char *unused) {
terminal_initialize();
return 0;
}
int get_gdt(char* unused) {
gdt_desc desc = {2,2};
int get_gdt(char *unused) {
gdt_desc desc = {2, 2};
sgdt(&desc);
terminal_writestring("limit = ");
terminal_writeint(desc.limit, 10);
@ -37,79 +38,77 @@ int get_gdt(char* unused) {
terminal_writeint(desc.base, 16);
terminal_putchar('\n');
gdt_entry* entries = (gdt_entry*) desc.base;
int num_entries = (desc.limit+1) / 8;
gdt_entry *entries = (gdt_entry *) desc.base;
int num_entries = (desc.limit + 1) / 8;
for (int entry_num = 0; entry_num < num_entries; entry_num++) {
gdt_entry entry = entries[entry_num];
uint32_t base = entry.base_lower | entry.base_middle << 16 | entry.base_higher << 24;
uint32_t limit = entry.limit_lower | (entry.flags_limit_higher & 0x0f) << 16;
uint8_t flags = (entry.flags_limit_higher >> 4);
bool is_data = ((entry.access_byte & 0b00001000) >> 3) == 0;
//terminal_writestring("\nEntry ");
//terminal_writeint(entry_num, 10);
terminal_writestring("base = 0x");
terminal_writeint(base, 16);
terminal_writestring("\nlimit = 0x");
terminal_writeint(limit, 16);
terminal_writestring("\nflags = 0b");
terminal_writeint((entry.flags_limit_higher >> 4), 2);
print("base = %x\n", base);
print("limit = %x\n", limit);
print("flags = %b\n", (entry.flags_limit_higher >> 4));
if ((flags & 0b1000) == 0) {
terminal_writestring(" (byte granularity");
print(" (byte granularity");
} else {
terminal_writestring(" (page granularity");
print(" (page granularity");
}
if ((flags & 0b0100) == 0) {
terminal_writestring(", 16 bit)");
print(", 16 bit)");
} else {
terminal_writestring(", 32 bit)");
print(", 32 bit)");
}
print("\n");
terminal_writestring("\naccess = 0b");
terminal_writeint(entry.access_byte, 2);
terminal_writestring(" (ring ");
terminal_writeint((entry.access_byte & 0b01100000) >> 5, 10);
print("access = %b (ring %d",
entry.access_byte,
(entry.access_byte & 0b01100000) >> 5
);
if ((entry.access_byte & 0b00010000) == 0) {
terminal_writestring(", System");
print(", System");
}
if (is_data) {
terminal_writestring(", Data");
print(", Data");
if((entry.access_byte & 0b00000100) == 0) {
terminal_writestring(" (growing up, ");
if ((entry.access_byte & 0b00000100) == 0) {
print(" (growing up, ");
} else {
terminal_writestring(" (growing down, ");
print(" (growing down, ");
}
if((entry.access_byte & 0b00000010) == 0) {
terminal_writestring("r--)");
if ((entry.access_byte & 0b00000010) == 0) {
print("r--)");
} else {
terminal_writestring("rw-)");
print("rw-)");
}
} else {
terminal_writestring(", Code");
print(", Code");
if((entry.access_byte & 0b00000100) == 0) {
terminal_writestring(" (non-conforming, ");
if ((entry.access_byte & 0b00000100) == 0) {
print(" (non-conforming, ");
} else {
terminal_writestring(" (conforming, ");
print(" (conforming, ");
}
if((entry.access_byte & 0b00000010) == 0) {
terminal_writestring("--x)");
if ((entry.access_byte & 0b00000010) == 0) {
print("--x)");
} else {
terminal_writestring("r-x)");
print("r-x)");
}
}
terminal_writestring(")\n");
print(")\n");
}
return 0;
}
int ree(char* unused) {
int ree(char *unused) {
terminal_initialize();
terminal_putchar('R');
for (int i = 1; i < VGA_WIDTH * VGA_HEIGHT; i++) {
@ -118,27 +117,41 @@ int ree(char* unused) {
return 0;
}
int save_text(char *text) {
char *mem_block = alloc(strlen(text) * sizeof(char));
char *c;
int i = 0;
for (c = text; *c != '\0'; c++) {
mem_block[i] = *c;
i++;
}
}
// TODO This is ugly, fix this
const char* shell_commands_strings[] = {
"echo",
"hello",
"cls",
"ree",
"getgdt",
NULL
const char *shell_commands_strings[] = {
"echo",
"hello",
"cls",
"ree",
"getgdt",
"memdump",
"savetext",
NULL
};
int (*shell_commands_functions[]) (char*) = {
echo,
hello,
cls,
ree,
get_gdt
int (*shell_commands_functions[])(char *) = {
echo,
hello,
cls,
ree,
get_gdt,
command_mem_dump,
save_text
};
int run_command(char* buffer) {
int run_command(char *buffer) {
if(buffer[0] == 0) {
if (buffer[0] == 0) {
return 0;
}
char command[SHELL_CMD_BUFFER_SIZE] = {0};
@ -150,9 +163,9 @@ int run_command(char* buffer) {
int command_idx = 0;
while(shell_commands_strings[command_idx] != NULL) {
while (shell_commands_strings[command_idx] != NULL) {
int check_idx = 0;
while(command[check_idx] != 0 && shell_commands_strings[command_idx][check_idx] == command[check_idx]) {
while (command[check_idx] != 0 && shell_commands_strings[command_idx][check_idx] == command[check_idx]) {
check_idx++;
}
if (command[check_idx] == 0 && shell_commands_strings[command_idx][check_idx] == 0) {
@ -176,7 +189,7 @@ void shell_step() {
buffer_idx = 0;
if (result == -1) {
terminal_writestring("No such command\n");
print("No such command\n");
}
} else if (curr_char == 0x08) {
if (buffer_idx != 0) {

91
kernel/tests/tests.c Normal file
View file

@ -0,0 +1,91 @@
#ifndef TESTS_TESTS_C
#define TESTS_TESTS_C
#define TESTS_ENABLED
#ifdef TESTS_ENABLED
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; \
if (message) return message; } while (0)
extern int tests_run;
#include "../memory.c"
#include <stddef.h>
int tests_run = 0;
static char *test_memory() {
ll_node *ll_head = __new_node();
ll_head->data = malloc(sizeof(size_t) * 5000);
ll_head->used = true;
ll_head->size = 1;
void *ptr0 = __alloc(ll_head, 5);
void *ptr1 = __alloc(ll_head, 5);
void *ptr4 = __alloc(ll_head, 5);
print(ll_head);
mu_assert("Error: chain should be complete at 1", ll_head->next != NULL);
mu_assert("Error: chain should be complete at 2", ll_head->next->next != NULL);
mu_assert("Error: chain should be complete at 3", ll_head->next->next->next != NULL);
mu_assert("Error: chain should be complete at 4", ll_head->next->next->next->next == NULL);
ll_node *current = ll_head;
while (current->next != NULL) {
current = current->next;
mu_assert("Error: block should have size 5", current->size == 5);
mu_assert("Error: block should be in use", current->used == true);
}
__free(ll_head, ptr1);
mu_assert("", ll_head->next->used == true);
mu_assert("", ll_head->next->next->used == false);
mu_assert("", ll_head->next->next->next->used == true);
printf("Alloc 3 bytes\n");
void *ptr2 = __alloc(ll_head, 3);
print(ll_head);
printf("Alloc 3 bytes\n");
__alloc(ll_head, 3);
print(ll_head);
printf("Alloc 2 bytes\n");
void *ptr3 = __alloc(ll_head, 2);
print(ll_head);
__free(ll_head, ptr2);
print(ll_head);
__free(ll_head, ptr4);
print(ll_head);
__free(ll_head, ptr3);
print(ll_head);
__free(ll_head, ptr0);
print(ll_head);
return 0;
}
static char *all_tests() {
mu_run_test(test_memory);
return 0;
}
//
//int main(int argc, char **argv) {
// char *result = all_tests();
// if (result != 0) {
// printf("%s\n", result);
// } else {
// printf("ALL TESTS PASSED\n");
// }
// printf("Tests run: %d\n", tests_run);
//
// return result != 0;
//}
#endif // TESTS_ENABLED
#endif // TESTS_TESTS_C

72
kernel/util/printer.c Normal file
View file

@ -0,0 +1,72 @@
#ifndef UTIL_PRINTER_C
#define UTIL_PRINTER_C
#include <stdarg.h>
#include "../terminal.c"
/**
* fmt is a string with specifiers where variables can be inserted.
*
* ex: ("Hello %s", "world") -> "Hello world"
*
* Specifiers are
* - %c: character
* - %d: digit (integer)
* - %x: hexadecimal value. Can be used to print pointers to
* - %b: binary value. Digits with base 2
* @param fmt Formatter string
* @param ... Variable amount of arguments to be inserted
*/
void print(const char *fmt, ...) {
const char *p;
va_list argp;
int i;
char *s;
char fmtbuf[256];
va_start(argp, fmt);
for (p = fmt; *p != '\0'; p++)
if (*p != '%') {
terminal_putchar(*p);
} else {
switch (*++p) {
case 'c':
i = va_arg(argp, int);
terminal_putchar((char) i);
break;
case 'd':
i = va_arg(argp, int);
s = itoa(i, fmtbuf, 10);
terminal_writestring(s);
break;
case 's':
s = va_arg(argp, char *);
terminal_writestring(s);
break;
case 'x':
terminal_writestring("0x");
i = va_arg(argp, int);
s = itoa(i, fmtbuf, 16);
terminal_writestring(s);
break;
case 'b':
terminal_writestring("0b");
i = va_arg(argp, int);
s = itoa(i, fmtbuf, 2);
terminal_writestring(s);
break;
case '%':
terminal_putchar('%');
break;
}
}
va_end(argp);
}
#endif //UTIL_PRINTER_C