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/ 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 - [ ] Write files in directory
- [ ] Tests - [ ] Tests
- [ ] Running executables from filesystem - [ ] Running executables from filesystem
- [ ] Better memory management - [x] Better memory management
- [ ] Better shell - [ ] 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). 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 or ax, ax
jnz .elf_ph_loop jnz .elf_ph_loop
.start_kernel .start_kernel:
cmp edi, KERNEL_START cmp edi, KERNEL_START
je .invalid_elf je .invalid_elf

View file

@ -16,6 +16,7 @@
#include "memory.c" #include "memory.c"
#include "interrupts.c" #include "interrupts.c"
#include "shell.c" #include "shell.c"
#include "util/printer.c"
static inline bool are_interrupts_enabled() { static inline bool are_interrupts_enabled() {
unsigned long flags; unsigned long flags;
@ -25,8 +26,7 @@ static inline bool are_interrupts_enabled() {
return flags & (1 << 9); return flags & (1 << 9);
} }
void kernel_main(void) void kernel_main(void) {
{
/* Initialize terminal interface */ /* Initialize terminal interface */
terminal_initialize(); terminal_initialize();
@ -37,10 +37,10 @@ void kernel_main(void)
terminal_putchar('o'); terminal_putchar('o');
terminal_setcolor(vga_entry_color(VGA_COLOR_GREEN, VGA_COLOR_BLACK)); 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_setcolor(vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
terminal_writestring(" World!\n"); print(" World!\n");
terminal_writestring("Newlines!\n"); print("Newlines!\n");
char *memory_str = alloc(sizeof(char) * 7); char *memory_str = alloc(sizeof(char) * 7);
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
@ -54,13 +54,28 @@ void kernel_main(void)
} }
management_str[13] = 0; management_str[13] = 0;
terminal_writestring(memory_str); print(memory_str);
terminal_writestring(management_str); print(management_str);
terminal_writestring((are_interrupts_enabled())? "Interrupts!\n": "No interrupts :(\n"); free(memory_str);
free(management_str);
// 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);
void* ptr2 = alloc(64);
alloc(61);
free(ptr2);
print((are_interrupts_enabled()) ? "Interrupts!\n" : "No interrupts :(\n");
interrupt_init(); interrupt_init();
print_memory();
for (;;) { for (;;) {
shell_step(); shell_step();
} }

View file

@ -1,13 +1,208 @@
#ifndef MEMORY_C #ifndef MEMORY_C
#define MEMORY_C #define MEMORY_C
#include <stddef.h> #include <stddef.h>
void* _curr_end = (void*) 0x200000; #include "terminal.c"
#include "util/printer.c"
#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);
}
void *alloc(size_t size) { void *alloc(size_t size) {
void* thanks_jp = _curr_end; page_tag *curr_page = start;
_curr_end += size;
return thanks_jp; 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 #endif // MEMORY_C

View file

@ -8,6 +8,7 @@
#include "terminal.c" #include "terminal.c"
#include "inline_asm.c" #include "inline_asm.c"
#include "drivers/keyboard/keyboard.c" #include "drivers/keyboard/keyboard.c"
#include "memory.c"
char buffer[SHELL_CMD_BUFFER_SIZE]; char buffer[SHELL_CMD_BUFFER_SIZE];
int buffer_idx = 0; int buffer_idx = 0;
@ -48,63 +49,61 @@ int get_gdt(char* unused) {
//terminal_writestring("\nEntry "); //terminal_writestring("\nEntry ");
//terminal_writeint(entry_num, 10); //terminal_writeint(entry_num, 10);
terminal_writestring("base = 0x"); print("base = %x\n", base);
terminal_writeint(base, 16); print("limit = %x\n", limit);
terminal_writestring("\nlimit = 0x"); print("flags = %b\n", (entry.flags_limit_higher >> 4));
terminal_writeint(limit, 16);
terminal_writestring("\nflags = 0b");
terminal_writeint((entry.flags_limit_higher >> 4), 2);
if ((flags & 0b1000) == 0) { if ((flags & 0b1000) == 0) {
terminal_writestring(" (byte granularity"); print(" (byte granularity");
} else { } else {
terminal_writestring(" (page granularity"); print(" (page granularity");
} }
if ((flags & 0b0100) == 0) { if ((flags & 0b0100) == 0) {
terminal_writestring(", 16 bit)"); print(", 16 bit)");
} else { } else {
terminal_writestring(", 32 bit)"); print(", 32 bit)");
} }
print("\n");
terminal_writestring("\naccess = 0b"); print("access = %b (ring %d",
terminal_writeint(entry.access_byte, 2); entry.access_byte,
terminal_writestring(" (ring "); (entry.access_byte & 0b01100000) >> 5
terminal_writeint((entry.access_byte & 0b01100000) >> 5, 10); );
if ((entry.access_byte & 0b00010000) == 0) { if ((entry.access_byte & 0b00010000) == 0) {
terminal_writestring(", System"); print(", System");
} }
if (is_data) { if (is_data) {
terminal_writestring(", Data"); print(", Data");
if ((entry.access_byte & 0b00000100) == 0) { if ((entry.access_byte & 0b00000100) == 0) {
terminal_writestring(" (growing up, "); print(" (growing up, ");
} else { } else {
terminal_writestring(" (growing down, "); print(" (growing down, ");
} }
if ((entry.access_byte & 0b00000010) == 0) { if ((entry.access_byte & 0b00000010) == 0) {
terminal_writestring("r--)"); print("r--)");
} else { } else {
terminal_writestring("rw-)"); print("rw-)");
} }
} else { } else {
terminal_writestring(", Code"); print(", Code");
if ((entry.access_byte & 0b00000100) == 0) { if ((entry.access_byte & 0b00000100) == 0) {
terminal_writestring(" (non-conforming, "); print(" (non-conforming, ");
} else { } else {
terminal_writestring(" (conforming, "); print(" (conforming, ");
} }
if ((entry.access_byte & 0b00000010) == 0) { if ((entry.access_byte & 0b00000010) == 0) {
terminal_writestring("--x)"); print("--x)");
} else { } else {
terminal_writestring("r-x)"); print("r-x)");
} }
} }
terminal_writestring(")\n"); print(")\n");
} }
return 0; return 0;
} }
@ -118,6 +117,16 @@ int ree(char* unused) {
return 0; 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 // TODO This is ugly, fix this
const char *shell_commands_strings[] = { const char *shell_commands_strings[] = {
"echo", "echo",
@ -125,6 +134,8 @@ const char* shell_commands_strings[] = {
"cls", "cls",
"ree", "ree",
"getgdt", "getgdt",
"memdump",
"savetext",
NULL NULL
}; };
@ -133,7 +144,9 @@ int (*shell_commands_functions[]) (char*) = {
hello, hello,
cls, cls,
ree, ree,
get_gdt get_gdt,
command_mem_dump,
save_text
}; };
int run_command(char *buffer) { int run_command(char *buffer) {
@ -176,7 +189,7 @@ void shell_step() {
buffer_idx = 0; buffer_idx = 0;
if (result == -1) { if (result == -1) {
terminal_writestring("No such command\n"); print("No such command\n");
} }
} else if (curr_char == 0x08) { } else if (curr_char == 0x08) {
if (buffer_idx != 0) { 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