summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Mikkelsen <petermikkelsen10@gmail.com>2025-07-29 21:40:45 +0200
committerPeter Mikkelsen <petermikkelsen10@gmail.com>2025-07-29 21:40:45 +0200
commit0a817a5a74c328229f8a732fc3ec22d8fd7dc20d (patch)
treea5f906687a28420a2ccb29c788e6779f221e7a75 /src
parentca84afb315e813f08d725082320d40969b9f93e4 (diff)
Some work on keeping track of memory, and providing more info in panics
Diffstat (limited to 'src')
-rw-r--r--src/aplos.h39
-rw-r--r--src/main.c57
-rw-r--r--src/nasty.S41
-rw-r--r--src/paging.c185
-rw-r--r--src/panic.c11
-rw-r--r--src/screen.c3
6 files changed, 280 insertions, 56 deletions
diff --git a/src/aplos.h b/src/aplos.h
index 7d3fce0..ad9109b 100644
--- a/src/aplos.h
+++ b/src/aplos.h
@@ -29,6 +29,40 @@ struct boot_info
uint64_t physbase;
};
+struct cpu_regs
+{
+ /* Keep this in sync with dump_regs in nasty.S */
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
+ uint64_t rflags;
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t cr8;
+ uint16_t cs;
+ uint16_t ds;
+ uint16_t ss;
+ uint16_t es;
+ uint16_t fs;
+ uint16_t gs;
+};
+
/* boot.c */
uint64_t cpu_count(void);
@@ -47,7 +81,7 @@ void main(struct boot_info *);
/* nasty.S */
struct table_reg;
-void halt(void);
+[[noreturn]] void halt(void);
void disable_interrupts(void);
void enable_interrupts(void);
void set_gdt(struct table_reg *, uint64_t, uint64_t, uint64_t);
@@ -55,13 +89,14 @@ void set_idt(struct table_reg *);
uint64_t get_cr2(void);
uint64_t get_cr3(void);
extern void (*isr_stubs[32])(void);
+void dump_regs(struct cpu_regs *);
/* paging.c */
void setup_paging(struct boot_info *);
bool page_fault_handler(uint32_t);
/* panic.c */
-void panic(void);
+[[noreturn]] void panic(void);
/* screen.c */
void screen_init(struct framebuffer *);
diff --git a/src/main.c b/src/main.c
index 03ad3fd..a3b7719 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,66 +1,15 @@
#include "aplos.h"
-static void welcome(void);
-static void print_memmap(struct boot_info *);
-static void print_size(uint64_t);
-
void
main(struct boot_info *info)
{
screen_init(&info->framebuffer);
- welcome();
+ print(u8"Starting ☺☻☺☻☺☻☺☻☺☻\n");
print(u8"CPU count: %u64\n", cpu_count());
- print_memmap(info);
setup_descriptors();
setup_paging(info);
-}
-
-static void
-welcome(void)
-{
- print(u8"Starting ☺☻☺☻☺☻☺☻☺☻\n");
-}
-
-static void
-print_memmap(struct boot_info *info)
-{
- print(u8"Usable memory: ");
- uint64_t total = 0;
- for(uint64_t i = 0; i < info->memmap_count; i++)
- total += info->memmaps[i].size;
- print_size(total);
- print(u8"\n");
-
- for(uint64_t i = 0; i < info->memmap_count; i++){
- struct memmap *m = &info->memmaps[i];
- print(u8"%p - %p (", m->start, m->start + m->size);
- print_size(m->size);
- print(u8")\n");
- }
-}
-
-static void
-print_size(uint64_t size)
-{
- uint64_t gb, mb, kb, b;
- gb = size >> 30; size -= gb << 30;
- mb = size >> 20; size -= mb << 20;
- kb = size >> 10; size -= kb << 10;
- b = size;
-
- int printed = 0;
-
-#define P(what, spec, force) \
- if(what || (force && !printed)){ \
- if(printed) \
- print(u8" + "); \
- printed = 1; \
- print(u8"%u64 " spec, what); \
- }
- P(gb, "GB", 0);
- P(mb, "MB", 0);
- P(kb, "KB", 0);
- P(b, "B", 1);
+ int *x = (int*)0xBEEF;
+ *x = 4; /* This should give us a page fault, and trigger the panic function */
}
diff --git a/src/nasty.S b/src/nasty.S
index 9fdab5f..f3d958e 100644
--- a/src/nasty.S
+++ b/src/nasty.S
@@ -106,3 +106,44 @@ DEFINE_ISRS
isr_stubs:
DEFINE_ISRS
#undef ISR
+
+.section .text
+.global dump_regs
+dump_regs:
+ mov [rdi+0], rax
+ mov [rdi+8], rbx
+ mov [rdi+16], rcx
+ mov [rdi+24], rdx
+ mov [rdi+32], rsi
+ mov [rdi+40], rdi
+ mov [rdi+48], rsp
+ mov [rdi+56], rbp
+ mov [rdi+64], r8
+ mov [rdi+72], r9
+ mov [rdi+80], r10
+ mov [rdi+88], r11
+ mov [rdi+96], r12
+ mov [rdi+104], r13
+ mov [rdi+112], r14
+ mov [rdi+120], r15
+ lea rax, [rip]
+ mov [rdi+128], rax
+ pushf
+ pop [rdi+136]
+ mov rax, cr0
+ mov [rdi+144], rax
+ mov rax, cr2
+ mov [rdi+152], rax
+ mov rax, cr3
+ mov [rdi+160], rax
+ mov rax, cr4
+ mov [rdi+168], rax
+ mov rax, cr8
+ mov [rdi+176], rax
+ mov [rdi+184], cs
+ mov [rdi+186], ds
+ mov [rdi+188], ss
+ mov [rdi+190], es
+ mov [rdi+192], fs
+ mov [rdi+194], gs
+ ret
diff --git a/src/paging.c b/src/paging.c
index 0728178..ecbd647 100644
--- a/src/paging.c
+++ b/src/paging.c
@@ -1,9 +1,50 @@
#include "aplos.h"
+#define MAX_REGIONS 1024
+#define INVALID_PTR UINT64_MAX
+
+struct region
+{
+ uint64_t start;
+ uint64_t size;
+ uint64_t next;
+ int available : 1;
+};
+
+struct region_map
+{
+ uint64_t used; /* Chain of used indices in the regions table */
+ uint64_t unused; /* Chain of unused indices in the regions table */
+ struct region regions[MAX_REGIONS];
+};
+
+static struct region_map physical;
+static struct region_map virtual;
+
+static void init_map(struct region_map *, bool);
+static void mark_region(struct region_map *, uint64_t, uint64_t, bool);
+static uint64_t lookup(struct region_map *, uint64_t);
+static void delete_node(struct region_map *, uint64_t);
+static uint64_t add_node(struct region_map *, uint64_t, uint64_t, bool);
+static void debug_region_map(struct region_map *);
+static void print_size(uint64_t);
+
void
setup_paging(struct boot_info *info)
{
print(u8"Setting up paging. All usable physical memory is mapped starting at %p\n", info->physbase);
+
+ init_map(&physical, false);
+ init_map(&virtual, true);
+
+ for(uint64_t i = 0; i < info->memmap_count; i++)
+ mark_region(&physical, info->memmaps[i].start, info->memmaps[i].size, true);
+ debug_region_map(&physical);
+
+ /* TODO fill in the used regions of virtual memory, by inspection the page tables that was setup for us
+ * by the bootloader.
+ */
+
uint64_t cr3 = get_cr3();
print(u8"CR3: %p\n", cr3);
}
@@ -18,3 +59,147 @@ page_fault_handler(uint32_t code)
return false; /* We didn't actually handle it */
}
+
+static void
+init_map(struct region_map *map, bool available)
+{
+ map->used = INVALID_PTR;
+ map->unused = 0;
+
+ for(uint64_t p = 0; p < MAX_REGIONS-1; p++)
+ map->regions[p].next = p+1;
+ map->regions[MAX_REGIONS-1].next = INVALID_PTR;
+
+ add_node(map, 0, UINT64_MAX, available);
+}
+
+static void
+mark_region(struct region_map *map, uint64_t addr, uint64_t size, bool available)
+{
+ uint64_t p = lookup(map, addr);
+ struct region *r = &map->regions[p];
+
+ if((r->start <= addr) && (r->start+r->size >= addr+size) && (r->available != available)){
+ /* Entirely within a current region. Split the current one up. */
+ uint64_t oldstart = r->start;
+ uint64_t oldend = r->start+r->size;
+ delete_node(map, p);
+ add_node(map, oldstart, addr - r->start, !available);
+ add_node(map, addr, size, available);
+ add_node(map, addr+size, oldend-(addr+size), !available);
+ }else
+ panic(); /* I don't want to think about this right now */
+}
+
+static uint64_t
+lookup(struct region_map *map, uint64_t addr)
+{
+ uint64_t p;
+ struct region *r;
+
+ for(p = map->used; p != INVALID_PTR; p = r->next){
+ r = &map->regions[p];
+ if((r->start <= addr) && (r->start+r->size > addr))
+ return p;
+ }
+ panic();
+}
+
+static void
+delete_node(struct region_map *map, uint64_t p)
+{
+ uint64_t x;
+ uint64_t prev = INVALID_PTR;
+ for(x = map->used; x != INVALID_PTR; prev = x, x = map->regions[x].next){
+ if(x == p){
+ if(prev != INVALID_PTR)
+ map->regions[prev].next = map->regions[x].next;
+ else
+ map->used = INVALID_PTR;
+ map->regions[x].next = map->unused;
+ map->unused = x;
+ return;
+ }
+ }
+ panic();
+}
+
+static uint64_t
+add_node(struct region_map *map, uint64_t start, uint64_t size, bool available)
+{
+ struct region *r;
+ uint64_t p;
+ uint64_t prev = INVALID_PTR;
+ for(p = map->used; p != INVALID_PTR; prev = p, p = map->regions[p].next){
+ if(map->regions[p].start > start)
+ break;
+ }
+
+ uint64_t new = map->unused;
+
+ if(prev == INVALID_PTR){
+ r = &map->regions[map->unused];
+ uint64_t tmp = map->used;
+ map->used = map->unused;
+ map->unused = r->next;
+ r->next = tmp;
+ }else{
+ r = &map->regions[map->unused];
+ map->unused = r->next;
+ r->next = map->regions[prev].next;
+ map->regions[prev].next = new;
+ }
+
+ r->start = start;
+ r->size = size;
+ r->available = available;
+ return new;
+}
+
+static void
+debug_region_map(struct region_map *map)
+{
+ uint64_t available = 0;
+ for(uint64_t p = map->used; p != INVALID_PTR; p = map->regions[p].next){
+ struct region *r = &map->regions[p];
+ if(r->available)
+ available += r->size;
+ }
+ print(u8"Total available memory: ");
+ print_size(available);
+ print(u8"\n");
+
+ for(uint64_t p = map->used; p != INVALID_PTR; p = map->regions[p].next){
+ struct region *r = &map->regions[p];
+ if(r->available){
+ print(u8"[%p - %p] (", r->start, r->start+r->size);
+ print_size(r->size);
+ print(u8")\n");
+ }
+ }
+}
+
+static void
+print_size(uint64_t size)
+{
+ uint64_t gb, mb, kb, b;
+ gb = size >> 30; size -= gb << 30;
+ mb = size >> 20; size -= mb << 20;
+ kb = size >> 10; size -= kb << 10;
+ b = size;
+
+ int printed = 0;
+
+#define P(what, spec, force) \
+ if(what || (force && !printed)){ \
+ if(printed) \
+ print(u8" + "); \
+ printed = 1; \
+ print(u8"%u64 " spec, what); \
+ }
+
+ P(gb, "GB", 0);
+ P(mb, "MB", 0);
+ P(kb, "KB", 0);
+ P(b, "B", 1);
+}
diff --git a/src/panic.c b/src/panic.c
index 5b17b04..3b39aeb 100644
--- a/src/panic.c
+++ b/src/panic.c
@@ -3,6 +3,17 @@
void
panic(void)
{
+ struct cpu_regs r;
+ dump_regs(&r);
+
print(u8"--- PANIC ---\n");
+ print(u8"rax: %p rbx: %p rcx: %p rdx: %p\n", r.rax, r.rbx, r.rcx, r.rdx);
+ print(u8"rsi: %p rdi: %p rsp: %p rbp: %p\n", r.rsi, r.rdi, r.rsp, r.rbp);
+ print(u8"r8: %p r9: %p r10: %p r11: %p\n", r.r9, r.r9, r.r10, r.r11);
+ print(u8"r12: %p r13: %p r14: %p r15: %p\n", r.r12, r.r13, r.r14, r.r15);
+ print(u8"rip: %p cr0: %p cr2: %p cr3: %p\n", r.rip, r.cr0, r.cr2, r.cr3);
+ print(u8"cr4: %p cr8: %p cs: %p ds: %p\n", r.cr4, r.cr8, r.cs, r.ds);
+ print(u8"ss: %p es: %p fs: %p gs: %p\n", r.ss, r.es, r.fs, r.gs);
+ print(u8"rflags: %p\n", r.rflags);
halt();
}
diff --git a/src/screen.c b/src/screen.c
index 903ce9c..46f1231 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -48,6 +48,9 @@ print_char:
row++;
col = 0;
break;
+ case '\t':
+ col = (col+8) & ~7;
+ break;
case '%':
n = print_fmt(p, args);
if(n == 0)