diff options
Diffstat (limited to 'src/kernel/dump.c')
-rw-r--r-- | src/kernel/dump.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/kernel/dump.c b/src/kernel/dump.c new file mode 100644 index 0000000..d0c02e6 --- /dev/null +++ b/src/kernel/dump.c @@ -0,0 +1,187 @@ +#include <stdint.h> + +#include "paging.h" +#include "task.h" +#include "log.h" + +extern const void _kernel_data_start; +extern const void _kernel_data_end; +extern const void _kernel_bss_end; + +static inline char c(uint8_t n) { + return (n > 0x20) && (n < 0x7f) ? (char)n : '.'; +} + +static uint8_t last_line[16]; +enum { + SECTION_START, + DOT_DOT_DOT, + SKIP +} last_line_mode; + +static void write_mem_line(uint32_t addr) { + const uint8_t *const at = (const uint8_t *)addr; + if (last_line_mode != SECTION_START) { + for (uint8_t i = 0; i < 16; ++i) + if (at[i] != last_line[i]) + goto diff_line; + if (last_line_mode == DOT_DOT_DOT) { + logf(LOG_DUMP, " 0x%h ...", addr); + last_line_mode = SKIP; + } + return; + } +diff_line: + logf(LOG_DUMP, + " 0x%h %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", addr, + at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7], + at[9], at[9], at[10], at[11], at[12], at[13], at[14], at[15], + c(at[0]), c(at[1]), c(at[2]), c(at[3]), + c(at[4]), c(at[5]), c(at[6]), c(at[7]), + c(at[8]), c(at[9]), c(at[10]), c(at[11]), + c(at[12]), c(at[13]), c(at[14]), c(at[15]) + ); + for (uint8_t i = 0; i < 16; ++i) + last_line[i] = at[1]; + last_line_mode = DOT_DOT_DOT; +} + +static void write_mem_page(uint32_t page) { + for (uint32_t i = page << 12; i < (page + 1) << 12; i += 16) + write_mem_line(i); +} + +#include "kbd.h" + +#define WAIT_TASK tasks[i].waits[t].task - tasks + 1, tasks[i].waits[t].task->name + +void dump(enum kbd_isr_result kind, const uint32_t edi, const uint32_t esi, const uint32_t ebx, const uint32_t edx, const uint32_t ecx, const uint32_t eax, const uint32_t eip, const uint32_t cs, const uint32_t eflags, const uint32_t esp, const uint32_t ss) { + uint32_t cr3; + asm volatile ( + "mov %%cr3, %0" + : "=a" (cr3)); + + logf(LOG_INFO, "Dump state..."); + + switch (kind) { + case DUMP: + logf(LOG_DUMP, "Tasks:"); + for (uint8_t t = 0; t < MAX_TASKS; ++t) + if (tasks[t].page_directory) { + logf(LOG_DUMP, " %s (0x%hb):", tasks[t].name, t + 1); + if (tasks + t == active_task) { + logf(LOG_DUMP, " *Active task*"); + logf(LOG_DUMP, " cr3: 0x%h", cr3); + logf(LOG_DUMP, " eip: 0x%h", eip); + logf(LOG_DUMP, " eax: 0x%h", eax); + logf(LOG_DUMP, " ebx: 0x%h", ebx); + logf(LOG_DUMP, " ecx: 0x%h", ecx); + logf(LOG_DUMP, " edx: 0x%h", edx); + logf(LOG_DUMP, " esi: 0x%h", esi); + logf(LOG_DUMP, " edi: 0x%h", edi); + logf(LOG_DUMP, " esp: 0x%h", esp); + logf(LOG_DUMP, " cs: 0x%hb", cs); + logf(LOG_DUMP, " ss: 0x%hb", ss); + logf(LOG_DUMP, " eflags: 0x%h", eflags); + } + else { + logf(LOG_DUMP, " Stored cr3: 0x%h", tasks[t].page_directory); + logf(LOG_DUMP, " Stored eip: 0x%h", tasks[t].ret_addr); + logf(LOG_DUMP, " Stored ebx: 0x%h", tasks[t].ebx); + logf(LOG_DUMP, " Stored ecx: 0x%h", tasks[t].ecx); + logf(LOG_DUMP, " Stored edx: 0x%h", tasks[t].edx); + logf(LOG_DUMP, " Stored esi: 0x%h", tasks[t].esi); + logf(LOG_DUMP, " Stored edi: 0x%h", tasks[t].edi); + logf(LOG_DUMP, " Stored ebp: 0x%h", tasks[t].ebp); + logf(LOG_DUMP, " Stored esp: 0x%h", tasks[t].esp); + } + logf(LOG_DUMP, " Stack size: %d kibibytes", -tasks[t].stack_bottom / 1024); + if (tasks[t].waiting) { + logf(LOG_DUMP, " Waits:"); + for (uint8_t i = 0; i < MAX_WAITS; ++i) + switch (tasks[i].waits[t].mode) { + case NONE: + continue; + case PROCESS_END: + logf(LOG_DUMP, " Waiting for task 0x%hb (%s) to end", WAIT_TASK); + continue; + case WINDOW_ACTION: + logf(LOG_DUMP, " Waiting for window action"); + continue; + case IPC_SENT: + logf(LOG_DUMP, " Waiting for IPC to be sent by 0x%hb (%s)", WAIT_TASK); + continue; + case IPC_SENT_ANY: + logf(LOG_DUMP, " Waiting for IPC to be sent by anyone"); + continue; + case IPC_READ: + logf(LOG_DUMP, " Waiting for IPC to be read by 0x%hb (%s)", WAIT_TASK); + continue; + default: + logf(LOG_DUMP, " Other (corrupted?)"); + continue; + } + } + else + logf(LOG_DUMP, " Not waiting."); + } + break; + + case SHIFT_DUMP: + + logf(LOG_DUMP, "Current task: 0x%hb (%s)", active_task - tasks + 1, active_task->name); + logf(LOG_DUMP, "Registers:"); + logf(LOG_DUMP, " cr3: 0x%h", cr3); + logf(LOG_DUMP, " eip: 0x%h", eip); + logf(LOG_DUMP, " esp: 0x%h", esp); + logf(LOG_DUMP, " eax: 0x%h", eax); + logf(LOG_DUMP, " ebx: 0x%h", ebx); + logf(LOG_DUMP, " ecx: 0x%h", ecx); + logf(LOG_DUMP, " edx: 0x%h", edx); + logf(LOG_DUMP, " esi: 0x%h", esi); + logf(LOG_DUMP, " edi: 0x%h", edi); + logf(LOG_DUMP, " eflags: 0x%h", eflags); + logf(LOG_DUMP, " cs: 0x%hb", cs); + logf(LOG_DUMP, " ss: 0x%hb", ss); + + logf(LOG_DUMP, "Kernel data section:"); + last_line_mode = SECTION_START; + for (uint32_t i = (uint32_t)&_kernel_data_start & ~0xf; i < (((uint32_t)&_kernel_data_end - 1) & ~0xf) + 0x10; i += 0x10) + write_mem_line(i); + logf(LOG_DUMP, "Kernel bss section:"); + last_line_mode = SECTION_START; + for (uint32_t i = 0x4000000; i < (((uint32_t)&_kernel_bss_end - 1) & ~0xf) + 1; i += 0x10) + write_mem_line(i); + logf(LOG_DUMP, "Kernel heap:"); + last_line_mode = SECTION_START; + const uint32_t first_heap_page = (((uint32_t)&_kernel_bss_end - 1) >> 12) + 1; + for (uint8_t n = first_heap_page & 7; n < 8; ++n) + if (*(uint8_t *)(0x40000 + (first_heap_page >> 3)) & (1 << n)) + write_mem_page((first_heap_page & ~7) | n); + for (uint8_t *i = (uint8_t *)(0x40000 + (first_heap_page >> 3) + 1); i < (uint8_t *)0x41000; ++i) + for (uint8_t n = 0; n < 8; ++n) + if (*i & (1 << n)) + write_mem_page((i - (uint8_t *)0x40000) * 8 + n); + + for (uint8_t t = 0; t < MAX_TASKS; ++t) + if (tasks[t].page_directory) { + logf(LOG_DUMP, "Task 0x%hb (%s)'s memory:", t + 1, tasks[t].name); + last_line_mode = SECTION_START; + const void *const pd = tasks[t].page_directory; + asm ( + "mov %0, %%cr3" + : : "a" (pd)); + for (uint32_t i = 0x08000000; i; i += 4096) + if (pd_is_mapped(pd, i)) + for (uint32_t j = i; j < i + 4096; j += 16) + write_mem_line(j); + } + break; + } + + logf(LOG_INFO, "Dumped state."); + + asm ( + "mov %0, %%cr3" + : : "a" (cr3)); +}
\ No newline at end of file |