formatting
This commit is contained in:
parent
821716adcc
commit
9e91024f35
9 changed files with 295 additions and 199 deletions
|
|
@ -3,43 +3,54 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <drivers/uart.h>
|
#include <drivers/uart.h>
|
||||||
|
|
||||||
void uart_put(size_t base_addr, uint8_t data) {
|
void uart_put(size_t base_addr, uint8_t data)
|
||||||
|
{
|
||||||
*(volatile uint8_t *)base_addr = data;
|
*(volatile uint8_t *)base_addr = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kputchar(int ch) {
|
int kputchar(int ch)
|
||||||
|
{
|
||||||
uart_put(UART_ADDRESS, ch);
|
uart_put(UART_ADDRESS, ch);
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kprint(const char *str) {
|
void kprint(const char *str)
|
||||||
while (*str) {
|
{
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
kputchar(*str++);
|
kputchar(*str++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void kprint_int(int num) {
|
void kprint_int(int num)
|
||||||
|
{
|
||||||
char buffer[21];
|
char buffer[21];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (num == 0) {
|
if (num == 0)
|
||||||
|
{
|
||||||
kputchar('0');
|
kputchar('0');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (num < 0) {
|
if (num < 0)
|
||||||
|
{
|
||||||
kputchar('-');
|
kputchar('-');
|
||||||
num = -num;
|
num = -num;
|
||||||
}
|
}
|
||||||
while (num > 0) {
|
while (num > 0)
|
||||||
|
{
|
||||||
buffer[i++] = '0' + (num % 10);
|
buffer[i++] = '0' + (num % 10);
|
||||||
num /= 10;
|
num /= 10;
|
||||||
}
|
}
|
||||||
while (i > 0) {
|
while (i > 0)
|
||||||
|
{
|
||||||
kputchar(buffer[--i]);
|
kputchar(buffer[--i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void kprint_float(float num) {
|
void kprint_float(float num)
|
||||||
if (num < 0) {
|
{
|
||||||
|
if (num < 0)
|
||||||
|
{
|
||||||
kputchar('-');
|
kputchar('-');
|
||||||
num = -num;
|
num = -num;
|
||||||
}
|
}
|
||||||
|
|
@ -47,20 +58,23 @@ void kprint_float(float num) {
|
||||||
float frac_part = num - int_part;
|
float frac_part = num - int_part;
|
||||||
kprint_int(int_part);
|
kprint_int(int_part);
|
||||||
kputchar('.');
|
kputchar('.');
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
frac_part *= 10.0f;
|
frac_part *= 10.0f;
|
||||||
}
|
}
|
||||||
int fraction = (int)(frac_part + 0.5f); // Round to nearest
|
int fraction = (int)(frac_part + 0.5f); // Round to nearest
|
||||||
kprint_int(fraction);
|
kprint_int(fraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kprint_hex(uint64_t val) {
|
void kprint_hex(uint64_t val)
|
||||||
|
{
|
||||||
char *digits = "0123456789ABCDEF";
|
char *digits = "0123456789ABCDEF";
|
||||||
char buffer[17]; // 64-bit hex is 16 chars
|
char buffer[17]; // 64-bit hex is 16 chars
|
||||||
buffer[16] = '\0'; // Null-terminate the string
|
buffer[16] = '\0'; // Null-terminate the string
|
||||||
|
|
||||||
// We process from right to left
|
// We process from right to left
|
||||||
for (int i = 15; i >= 0; i--) {
|
for (int i = 15; i >= 0; i--)
|
||||||
|
{
|
||||||
buffer[i] = digits[val & 0xF];
|
buffer[i] = digits[val & 0xF];
|
||||||
val >>= 4;
|
val >>= 4;
|
||||||
}
|
}
|
||||||
|
|
@ -68,40 +82,50 @@ void kprint_hex(uint64_t val) {
|
||||||
kprint(buffer);
|
kprint(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void knewline(void) {
|
void knewline(void)
|
||||||
|
{
|
||||||
kputchar('\n');
|
kputchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
void kputs(const char *str) {
|
void kputs(const char *str)
|
||||||
|
{
|
||||||
kprint(str);
|
kprint(str);
|
||||||
knewline();
|
knewline();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kprintf(const char *format, ...) {
|
void kprintf(const char *format, ...)
|
||||||
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
for(char *p = format; *p != '\0'; p++) {
|
for (char *p = format; *p != '\0'; p++)
|
||||||
if (*p == '%') {
|
{
|
||||||
|
if (*p == '%')
|
||||||
|
{
|
||||||
p++;
|
p++;
|
||||||
switch (*p) {
|
switch (*p)
|
||||||
case 's': {
|
{
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
char *s = va_arg(args, char *);
|
char *s = va_arg(args, char *);
|
||||||
kprint(s);
|
kprint(s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd': {
|
case 'd':
|
||||||
|
{
|
||||||
int d = va_arg(args, int);
|
int d = va_arg(args, int);
|
||||||
kprint_int(d);
|
kprint_int(d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f': {
|
case 'f':
|
||||||
|
{
|
||||||
double f = va_arg(args, double);
|
double f = va_arg(args, double);
|
||||||
kprint_float((float)f);
|
kprint_float((float)f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x': // Hex
|
case 'x': // Hex
|
||||||
case 'p': { // Pointer
|
case 'p':
|
||||||
|
{ // Pointer
|
||||||
uint64_t x = va_arg(args, uint64_t);
|
uint64_t x = va_arg(args, uint64_t);
|
||||||
kprint_hex(x);
|
kprint_hex(x);
|
||||||
break;
|
break;
|
||||||
|
|
@ -113,7 +137,9 @@ void kprintf(const char *format, ...) {
|
||||||
kputchar('%');
|
kputchar('%');
|
||||||
kputchar(*p);
|
kputchar(*p);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
kputchar(*p);
|
kputchar(*p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,12 @@
|
||||||
#include <kernel/panic.h>
|
#include <kernel/panic.h>
|
||||||
#include <kernel/memory.h>
|
#include <kernel/memory.h>
|
||||||
|
|
||||||
void kmain() {
|
void kmain()
|
||||||
kprintf("Hello, from %s!" , "SquidgeOS");
|
{
|
||||||
|
kprintf("Hello, from %s!", "SquidgeOS");
|
||||||
kputs("-------------------");
|
kputs("-------------------");
|
||||||
knewline();
|
knewline();
|
||||||
page_init();
|
page_init();
|
||||||
|
|
||||||
//kprint("Stress testing memory...\n");
|
|
||||||
//while(1) {
|
|
||||||
// void *p = page_alloc();
|
|
||||||
//}
|
|
||||||
|
|
||||||
test_memory_integrity();
|
test_memory_integrity();
|
||||||
test_memory_alignment();
|
test_memory_alignment();
|
||||||
test_memory_stress();
|
test_memory_stress();
|
||||||
|
|
|
||||||
|
|
@ -4,51 +4,60 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
|
||||||
|
HeapHeader *heap_free_list;
|
||||||
HeapHeader* heap_free_list;
|
|
||||||
extern uint8_t _heap_start[]; // named in the linker script
|
extern uint8_t _heap_start[]; // named in the linker script
|
||||||
|
|
||||||
void page_init() {
|
void page_init()
|
||||||
|
{
|
||||||
kprint("Initialising page allocator.\n");
|
kprint("Initialising page allocator.\n");
|
||||||
uintptr_t start = ((uintptr_t)_heap_start + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
uintptr_t start = ((uintptr_t)_heap_start + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||||
uintptr_t end = 0x88000000; // Default QEMU RAM limit
|
uintptr_t end = 0x88000000; // Default QEMU RAM limit
|
||||||
|
|
||||||
for (uintptr_t addr = start; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
|
for (uintptr_t addr = start; addr + PAGE_SIZE <= end; addr += PAGE_SIZE)
|
||||||
|
{
|
||||||
page_free((void *)addr);
|
page_free((void *)addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void page_free(void *addr) {
|
void page_free(void *addr)
|
||||||
if (addr == NULL) return;
|
{
|
||||||
|
if (addr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
struct Page *p = (struct Page *)addr;
|
struct Page *p = (struct Page *)addr;
|
||||||
p->next = free_list;
|
p->next = free_list;
|
||||||
free_list = p;
|
free_list = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *page_alloc() {
|
void *page_alloc()
|
||||||
if (free_list == NULL) {
|
{
|
||||||
|
if (free_list == NULL)
|
||||||
|
{
|
||||||
kpanic("No free pages!");
|
kpanic("No free pages!");
|
||||||
}
|
}
|
||||||
struct Page *p = free_list;
|
struct Page *p = free_list;
|
||||||
free_list = free_list->next;
|
free_list = free_list->next;
|
||||||
|
|
||||||
//zero out the page
|
// zero out the page
|
||||||
for (int i = 0; i < (PAGE_SIZE); i++) {
|
for (int i = 0; i < (PAGE_SIZE); i++)
|
||||||
|
{
|
||||||
((uint8_t *)p)[i] = 0;
|
((uint8_t *)p)[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)p;
|
return (void *)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *kmalloc(size_t size) {
|
void *kmalloc(size_t size)
|
||||||
if (size == 0) return NULL;
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Align size to 8 bytes
|
// Align size to 8 bytes
|
||||||
size = (size + 7) & ~7;
|
size = (size + 7) & ~7;
|
||||||
|
|
||||||
if (heap_free_list == NULL) {
|
if (heap_free_list == NULL)
|
||||||
HeapHeader* header = (HeapHeader *)page_alloc();
|
{
|
||||||
|
HeapHeader *header = (HeapHeader *)page_alloc();
|
||||||
header->size = PAGE_SIZE - sizeof(HeapHeader);
|
header->size = PAGE_SIZE - sizeof(HeapHeader);
|
||||||
header->is_free = 1;
|
header->is_free = 1;
|
||||||
header->next = NULL;
|
header->next = NULL;
|
||||||
|
|
@ -60,22 +69,26 @@ void *kmalloc(size_t size) {
|
||||||
HeapHeader *current = heap_free_list;
|
HeapHeader *current = heap_free_list;
|
||||||
HeapHeader *prev = NULL;
|
HeapHeader *prev = NULL;
|
||||||
|
|
||||||
while (current != NULL) {
|
while (current != NULL)
|
||||||
if (current->is_free && current->size >= size) {
|
{
|
||||||
|
if (current->is_free && current->size >= size)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev = current;
|
prev = current;
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current == NULL) {
|
if (current == NULL)
|
||||||
|
{
|
||||||
// No suitable block found, allocate a new page
|
// No suitable block found, allocate a new page
|
||||||
HeapHeader* header = (HeapHeader *)page_alloc();
|
HeapHeader *header = (HeapHeader *)page_alloc();
|
||||||
header->size = PAGE_SIZE - sizeof(HeapHeader);
|
header->size = PAGE_SIZE - sizeof(HeapHeader);
|
||||||
header->is_free = 1;
|
header->is_free = 1;
|
||||||
header->next = heap_free_list;
|
header->next = heap_free_list;
|
||||||
header->prev = NULL;
|
header->prev = NULL;
|
||||||
if(heap_free_list) {
|
if (heap_free_list)
|
||||||
|
{
|
||||||
heap_free_list->prev = header;
|
heap_free_list->prev = header;
|
||||||
}
|
}
|
||||||
heap_free_list = header;
|
heap_free_list = header;
|
||||||
|
|
@ -83,7 +96,8 @@ void *kmalloc(size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, current is a block that can be used
|
// Now, current is a block that can be used
|
||||||
if (!current) {
|
if (!current)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,10 +105,12 @@ void *kmalloc(size_t size) {
|
||||||
|
|
||||||
// If the block is larger than needed, split it
|
// If the block is larger than needed, split it
|
||||||
size_t min_split_size = sizeof(HeapHeader) + 16;
|
size_t min_split_size = sizeof(HeapHeader) + 16;
|
||||||
if (current->size >= size + min_split_size) {
|
if (current->size >= size + min_split_size)
|
||||||
|
{
|
||||||
HeapHeader *new_header = (HeapHeader *)((uint8_t *)current + sizeof(HeapHeader) + size);
|
HeapHeader *new_header = (HeapHeader *)((uint8_t *)current + sizeof(HeapHeader) + size);
|
||||||
// Safety check: if new_header address is wild, abort!
|
// Safety check: if new_header address is wild, abort!
|
||||||
if ((uintptr_t)new_header < 0x80000000 || (uintptr_t)new_header > 0x88000000) {
|
if ((uintptr_t)new_header < 0x80000000 || (uintptr_t)new_header > 0x88000000)
|
||||||
|
{
|
||||||
kpanic("Splitting created invalid pointer!");
|
kpanic("Splitting created invalid pointer!");
|
||||||
}
|
}
|
||||||
new_header->size = current->size - size - sizeof(HeapHeader);
|
new_header->size = current->size - size - sizeof(HeapHeader);
|
||||||
|
|
@ -102,21 +118,25 @@ void *kmalloc(size_t size) {
|
||||||
|
|
||||||
new_header->next = current->next;
|
new_header->next = current->next;
|
||||||
new_header->prev = current;
|
new_header->prev = current;
|
||||||
if(current->next) {
|
if (current->next)
|
||||||
|
{
|
||||||
current->next->prev = new_header;
|
current->next->prev = new_header;
|
||||||
}
|
}
|
||||||
current->size = size;
|
current->size = size;
|
||||||
current->next = new_header;
|
current->next = new_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void*)((char*)current + sizeof(HeapHeader));
|
return (void *)((char *)current + sizeof(HeapHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
void kfree(void *ptr) {
|
void kfree(void *ptr)
|
||||||
if (ptr == NULL) return;
|
{
|
||||||
|
if (ptr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
HeapHeader *header = (HeapHeader *)((uint8_t *)ptr - sizeof(HeapHeader));
|
HeapHeader *header = (HeapHeader *)((uint8_t *)ptr - sizeof(HeapHeader));
|
||||||
if(header->is_free) {
|
if (header->is_free)
|
||||||
|
{
|
||||||
kpanic("Double free detected!");
|
kpanic("Double free detected!");
|
||||||
}
|
}
|
||||||
header->is_free = 1;
|
header->is_free = 1;
|
||||||
|
|
@ -124,49 +144,64 @@ void kfree(void *ptr) {
|
||||||
kcoalesce(header);
|
kcoalesce(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kcoalesce(HeapHeader *header) {
|
void kcoalesce(HeapHeader *header)
|
||||||
if(!header || !header->is_free) return;
|
{
|
||||||
//merge backward
|
if (!header || !header->is_free)
|
||||||
while (header->prev && header->prev->is_free) {
|
return;
|
||||||
|
// merge backward
|
||||||
|
while (header->prev && header->prev->is_free)
|
||||||
|
{
|
||||||
header = header->prev;
|
header = header->prev;
|
||||||
}
|
}
|
||||||
//merge forward
|
// merge forward
|
||||||
while (header->next && header->next->is_free){
|
while (header->next && header->next->is_free)
|
||||||
|
{
|
||||||
uintptr_t current_end = (uintptr_t)header + sizeof(HeapHeader) + header->size;
|
uintptr_t current_end = (uintptr_t)header + sizeof(HeapHeader) + header->size;
|
||||||
if (current_end == (uintptr_t)header->next) {
|
if (current_end == (uintptr_t)header->next)
|
||||||
|
{
|
||||||
header->size += sizeof(HeapHeader) + header->next->size;
|
header->size += sizeof(HeapHeader) + header->next->size;
|
||||||
header->next = header->next->next;
|
header->next = header->next->next;
|
||||||
if(header->next) {
|
if (header->next)
|
||||||
|
{
|
||||||
header->next->prev = header;
|
header->next->prev = header;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_memory_integrity() {
|
void test_memory_integrity()
|
||||||
|
{
|
||||||
kprint("Running Integrity Test...\n");
|
kprint("Running Integrity Test...\n");
|
||||||
uint64_t *a = (uint64_t*)kmalloc(16);
|
uint64_t *a = (uint64_t *)kmalloc(16);
|
||||||
uint64_t *b = (uint64_t*)kmalloc(16);
|
uint64_t *b = (uint64_t *)kmalloc(16);
|
||||||
|
|
||||||
*a = 0x1122334455667788;
|
*a = 0x1122334455667788;
|
||||||
*b = 0x99AABBCCDDEEFF00;
|
*b = 0x99AABBCCDDEEFF00;
|
||||||
|
|
||||||
if (*a == 0x1122334455667788) {
|
if (*a == 0x1122334455667788)
|
||||||
|
{
|
||||||
kprint("Integrity Pass!\n");
|
kprint("Integrity Pass!\n");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
kprint("CORRUPTION DETECTED!\n");
|
kprint("CORRUPTION DETECTED!\n");
|
||||||
}
|
}
|
||||||
kfree(a);
|
kfree(a);
|
||||||
kfree(b);
|
kfree(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_memory_alignment() {
|
void test_memory_alignment()
|
||||||
|
{
|
||||||
kprint("Running Alignment Test...\n");
|
kprint("Running Alignment Test...\n");
|
||||||
for (int i = 1; i <= 64; i++) {
|
for (int i = 1; i <= 64; i++)
|
||||||
|
{
|
||||||
void *ptr = kmalloc(i);
|
void *ptr = kmalloc(i);
|
||||||
if (((uintptr_t)ptr % 8) != 0) {
|
if (((uintptr_t)ptr % 8) != 0)
|
||||||
|
{
|
||||||
kprint("Misaligned allocation detected!\n");
|
kprint("Misaligned allocation detected!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -175,20 +210,25 @@ void test_memory_alignment() {
|
||||||
kprint("All allocations are properly aligned!\n");
|
kprint("All allocations are properly aligned!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_memory_stress() {
|
void test_memory_stress()
|
||||||
|
{
|
||||||
kprintf("Starting Stress Test...\n");
|
kprintf("Starting Stress Test...\n");
|
||||||
heap_stats();
|
heap_stats();
|
||||||
void *ptrs[100] = {0}; // Track allocated pointers
|
void *ptrs[100] = {0}; // Track allocated pointers
|
||||||
uint32_t seed = 0xACE2026; // Example seed
|
uint32_t seed = 0xACE2026; // Example seed
|
||||||
|
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
// 1. Randomly allocate or free
|
// 1. Randomly allocate or free
|
||||||
int idx = (seed >> 16) % 50;
|
int idx = (seed >> 16) % 50;
|
||||||
if (ptrs[idx] == NULL) {
|
if (ptrs[idx] == NULL)
|
||||||
|
{
|
||||||
size_t size = (seed % 256) + 1;
|
size_t size = (seed % 256) + 1;
|
||||||
ptrs[idx] = kmalloc(size);
|
ptrs[idx] = kmalloc(size);
|
||||||
// Optional: fill with data to check integrity later
|
// Optional: fill with data to check integrity later
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
kfree(ptrs[idx]);
|
kfree(ptrs[idx]);
|
||||||
ptrs[idx] = NULL;
|
ptrs[idx] = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -199,8 +239,10 @@ void test_memory_stress() {
|
||||||
kprintf("HeadHeader size: %d bytes\n", sizeof(HeapHeader));
|
kprintf("HeadHeader size: %d bytes\n", sizeof(HeapHeader));
|
||||||
heap_stats();
|
heap_stats();
|
||||||
kprintf("Cleaning up remaining allocations...\n");
|
kprintf("Cleaning up remaining allocations...\n");
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++)
|
||||||
if (ptrs[i] != NULL) {
|
{
|
||||||
|
if (ptrs[i] != NULL)
|
||||||
|
{
|
||||||
kfree(ptrs[i]);
|
kfree(ptrs[i]);
|
||||||
ptrs[i] = NULL;
|
ptrs[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +250,8 @@ void test_memory_stress() {
|
||||||
heap_stats();
|
heap_stats();
|
||||||
}
|
}
|
||||||
|
|
||||||
void heap_stats() {
|
void heap_stats()
|
||||||
|
{
|
||||||
size_t free_size = 0;
|
size_t free_size = 0;
|
||||||
size_t used_size = 0;
|
size_t used_size = 0;
|
||||||
size_t free_blocks = 0;
|
size_t free_blocks = 0;
|
||||||
|
|
@ -216,11 +259,15 @@ void heap_stats() {
|
||||||
|
|
||||||
HeapHeader *current = heap_free_list;
|
HeapHeader *current = heap_free_list;
|
||||||
|
|
||||||
while (current != NULL) {
|
while (current != NULL)
|
||||||
if (current->is_free) {
|
{
|
||||||
|
if (current->is_free)
|
||||||
|
{
|
||||||
free_size += current->size;
|
free_size += current->size;
|
||||||
free_blocks++;
|
free_blocks++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
used_size += current->size;
|
used_size += current->size;
|
||||||
used_blocks++;
|
used_blocks++;
|
||||||
}
|
}
|
||||||
|
|
@ -231,7 +278,7 @@ void heap_stats() {
|
||||||
kprintf("Page Size: %d bytes", PAGE_SIZE);
|
kprintf("Page Size: %d bytes", PAGE_SIZE);
|
||||||
kprintf("HeapHeader size: %d bytes", sizeof(HeapHeader));
|
kprintf("HeapHeader size: %d bytes", sizeof(HeapHeader));
|
||||||
kprintf("Pages allocated: %d", (used_size + free_size + used_blocks * sizeof(HeapHeader) + free_blocks * sizeof(HeapHeader)) / PAGE_SIZE);
|
kprintf("Pages allocated: %d", (used_size + free_size + used_blocks * sizeof(HeapHeader) + free_blocks * sizeof(HeapHeader)) / PAGE_SIZE);
|
||||||
kprintf("Used: %x bytes in %d blocks",used_size, used_blocks);
|
kprintf("Used: %x bytes in %d blocks", used_size, used_blocks);
|
||||||
kprintf("Used (with overhead): %x bytes", used_size + used_blocks * sizeof(HeapHeader));
|
kprintf("Used (with overhead): %x bytes", used_size + used_blocks * sizeof(HeapHeader));
|
||||||
kprintf("Free: %x bytes in %d blocks", free_size, free_blocks);
|
kprintf("Free: %x bytes in %d blocks", free_size, free_blocks);
|
||||||
kprintf("Total metadata overhead: %d bytes", ((used_blocks + free_blocks) * sizeof(HeapHeader)));
|
kprintf("Total metadata overhead: %d bytes", ((used_blocks + free_blocks) * sizeof(HeapHeader)));
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
typedef struct Page {
|
typedef struct Page
|
||||||
|
{
|
||||||
struct Page *next;
|
struct Page *next;
|
||||||
} Page;
|
} Page;
|
||||||
|
|
||||||
typedef struct HeapHeader {
|
typedef struct HeapHeader
|
||||||
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
int is_free;
|
int is_free;
|
||||||
struct HeapHeader *next;
|
struct HeapHeader *next;
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,16 @@
|
||||||
#include <syscon/syscon.h>
|
#include <syscon/syscon.h>
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
void kpanic(const char *reason){
|
void kpanic(const char *reason)
|
||||||
|
{
|
||||||
kputs("\n!!! PANIC !!!\n");
|
kputs("\n!!! PANIC !!!\n");
|
||||||
kputs(reason);
|
kputs(reason);
|
||||||
kputs("\n!!! PANIC !!!\n");
|
kputs("\n!!! PANIC !!!\n");
|
||||||
poweroff();
|
poweroff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kpanic_force() {
|
void kpanic_force()
|
||||||
|
{
|
||||||
kprint("\n!!! FORCE PANIC !!!\n");
|
kprint("\n!!! FORCE PANIC !!!\n");
|
||||||
|
|
||||||
// 'ebreak' is the standard RISC-V way to trigger a debug trap.
|
// 'ebreak' is the standard RISC-V way to trigger a debug trap.
|
||||||
|
|
@ -21,12 +23,14 @@ void kpanic_force() {
|
||||||
poweroff();
|
poweroff();
|
||||||
|
|
||||||
kprint("Force panic falled. Power off failed. sleep until interupt. \n");
|
kprint("Force panic falled. Power off failed. sleep until interupt. \n");
|
||||||
while(1) {
|
while (1)
|
||||||
|
{
|
||||||
__asm__ volatile("wfi");
|
__asm__ volatile("wfi");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_trap() {
|
void handle_trap()
|
||||||
|
{
|
||||||
kprint("\n!!! HARDWARE EXCEPTION DETECTED !!!\n");
|
kprint("\n!!! HARDWARE EXCEPTION DETECTED !!!\n");
|
||||||
|
|
||||||
// Read the 'mcause' register to see WHY we trapped
|
// Read the 'mcause' register to see WHY we trapped
|
||||||
|
|
@ -37,15 +41,32 @@ void handle_trap() {
|
||||||
uintptr_t mtval;
|
uintptr_t mtval;
|
||||||
asm volatile("csrr %0, mtval" : "=r"(mtval));
|
asm volatile("csrr %0, mtval" : "=r"(mtval));
|
||||||
|
|
||||||
switch(cause) {
|
switch (cause)
|
||||||
case 0: kprint("Reason: Instruction Address Misaligned\n"); break;
|
{
|
||||||
case 1: kprint("Reason: Instruction Access Fault\n"); break;
|
case 0:
|
||||||
case 2: kprint("Reason: Illegal Instruction\n"); break;
|
kprint("Reason: Instruction Address Misaligned\n");
|
||||||
case 3: kprint("Reason: Breakpoint (ebreak)\n"); break;
|
break;
|
||||||
case 4: kprint("Reason: Load Address Misaligned\n"); break;
|
case 1:
|
||||||
case 5: kprint("Reason: Load Access Fault\n"); break;
|
kprint("Reason: Instruction Access Fault\n");
|
||||||
case 6: kprint("Reason: Store/AMO Address Misaligned\n"); break;
|
break;
|
||||||
case 7: kprint("Reason: Store/AMO Access Fault\n"); break;
|
case 2:
|
||||||
|
kprint("Reason: Illegal Instruction\n");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
kprint("Reason: Breakpoint (ebreak)\n");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
kprint("Reason: Load Address Misaligned\n");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
kprint("Reason: Load Access Fault\n");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
kprint("Reason: Store/AMO Address Misaligned\n");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
kprint("Reason: Store/AMO Access Fault\n");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
kprintf("Reason: Unknown Exception Code %d\n", cause);
|
kprintf("Reason: Unknown Exception Code %d\n", cause);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ void kpanic(const char *reason);
|
||||||
void kpanic_force();
|
void kpanic_force();
|
||||||
|
|
||||||
#define KASSERT(cond, msg) \
|
#define KASSERT(cond, msg) \
|
||||||
if (!(cond)) { \
|
if (!(cond)) \
|
||||||
|
{ \
|
||||||
kprint("ASSERTION FAILED: "); \
|
kprint("ASSERTION FAILED: "); \
|
||||||
kprint(__FILE__); \
|
kprint(__FILE__); \
|
||||||
kprint(":"); \
|
kprint(":"); \
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t n) {
|
void *memset(void *s, int c, size_t n)
|
||||||
|
{
|
||||||
unsigned char *p = s;
|
unsigned char *p = s;
|
||||||
while (n--) {
|
while (n--)
|
||||||
|
{
|
||||||
*p++ = (unsigned char)c;
|
*p++ = (unsigned char)c;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
#include "syscon.h"
|
#include "syscon.h"
|
||||||
#include "drivers/uart.h"
|
#include "drivers/uart.h"
|
||||||
|
|
||||||
void poweroff(void) {
|
void poweroff(void)
|
||||||
|
{
|
||||||
knewline();
|
knewline();
|
||||||
kputs("-------");
|
kputs("-------");
|
||||||
knewline();
|
knewline();
|
||||||
|
|
@ -11,7 +12,8 @@ void poweroff(void) {
|
||||||
*(volatile uint32_t *)SYSCON_ADDR = SYSCON_POWEROFF;
|
*(volatile uint32_t *)SYSCON_ADDR = SYSCON_POWEROFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reboot(void) {
|
void reboot(void)
|
||||||
|
{
|
||||||
knewline();
|
knewline();
|
||||||
kputs("-------");
|
kputs("-------");
|
||||||
knewline();
|
knewline();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue