#include #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[t].waits[i].task->name, tasks[t].waits[i].task - tasks + 1 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[t].waits[i].mode) { case NONE: continue; case PROCESS_END: logf(LOG_DUMP, " Waiting for task %s (0x%hb) 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 %s (0x%hb)", 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 %s (0x%hb)", 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)); }