123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- /*
- * crash.c
- *
- * Copyright (C) 2018 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <common.h>
- #include <exception.h>
- #include <process.h>
- #include <module.h>
- #include <memory.h>
- #include <log.h>
- #include <exec/elf.h>
- #define MAX_BACKTRACE 256
- /* The background is a fabulous compromise between blue and red */
- #define CRASH_SCREEN_ATTRIBUTE 0x5F
- extern bool_t video_initialized;
- extern const char *lookup_kernel_symbol_name(uintptr_t address);
- static char screen[TEXT_WIDTH * TEXT_HEIGHT + 1] = { 0 };
- static const char *screen_template[TEXT_HEIGHT] = {
- "",
- " >>> KERNEL CRASH <<<",
- "",
- " A fatal error has occurred in the Monolithium kernel. The system cannot",
- " continue from this point in a reliable manner, and has been shut down.",
- " Please contact the developers so that similar issues can be prevented or",
- " avoided in the future.",
- "",
- " Error: %.71s",
- " %.78s",
- " In %s line %u",
- " Modules involved: %.60s",
- "",
- " If serial logging is enabled, more information might be available in the log.",
- };
- void __attribute__((noreturn)) kernel_crash(const char *message, registers_t *regs, const char *filename, int line)
- {
- int i;
- word_t *video_mem = (word_t*)(video_initialized ? VIDEO_MEMORY : TEXT_VIDEO_MEMORY);
- cpu_disable_interrupts();
- uintptr_t call_stack[MAX_BACKTRACE];
- int call_count = 0;
- uintptr_t *frame_pointer;
- asm volatile ("movl %%ebp, %0" : "=r"(frame_pointer) ::);
- while (frame_pointer && call_count < MAX_BACKTRACE)
- {
- if (!get_physical_address(&frame_pointer[1])) break;
- call_stack[call_count++] = frame_pointer[1];
- if (!get_physical_address(&frame_pointer[0])) break;
- frame_pointer = (uintptr_t*)frame_pointer[0];
- }
- for (i = 0; i < TEXT_HEIGHT; i++)
- {
- if (!screen_template[i]) continue;
- switch (i)
- {
- case 8:
- sprintf(&screen[i * TEXT_WIDTH], screen_template[i], message);
- break;
- case 9:
- if (strlen(message) > 71) sprintf(&screen[i * TEXT_WIDTH], screen_template[i], &message[71]);
- break;
- case 10:
- sprintf(&screen[i * TEXT_WIDTH], screen_template[i], filename, line);
- break;
- case 11:
- {
- int module_count = 0, j, k;
- const char *module_list[call_count];
- char modules[61] = "";
- for (j = 0; j < call_count; j++)
- {
- module_t *module = get_module_from_address((void*)call_stack[j]);
- if (!module) continue;
- bool_t found = FALSE;
- for (k = 0; k < module_count; k++)
- {
- if (strcmp(module_list[k], module->name) == 0)
- {
- found = TRUE;
- break;
- }
- }
- if (found) continue;
- module_list[module_count++] = module->name;
- if (module_count) strncat(modules, ", ", sizeof(modules) - strlen(modules) - 1);
- strncat(modules, module_list[j], sizeof(modules) - strlen(modules) - 1);
- }
- if (!strlen(modules)) sprintf(modules, "(none)");
- sprintf(&screen[i * TEXT_WIDTH], screen_template[i], modules);
- }
- break;
- default:
- strcpy(&screen[i * TEXT_WIDTH], screen_template[i]);
- }
- }
-
- for (i = 0; i < TEXT_WIDTH * TEXT_HEIGHT; i++) video_mem[i] = (CRASH_SCREEN_ATTRIBUTE << 8) | screen[i];
- log_write(LOG_CRITICAL, "******************************\n");
- log_write(LOG_CRITICAL, "* ATTENTION!!! *\n");
- log_write(LOG_CRITICAL, "******************************\n");
- log_write(LOG_CRITICAL, "The kernel crashed, specifying the following message:\n");
- log_write(LOG_CRITICAL, "%s\n", message);
- log_write(LOG_CRITICAL, "Crash requested in file %s line %u\n", filename, line);
- thread_t *thread = get_current_thread();
- if (thread)
- {
- log_write(LOG_CRITICAL, "Context: thread %u", thread->tid);
- if (thread->owner_process)
- {
- log_write(LOG_CRITICAL, ", attached to process %u (%s).\n", thread->owner_process->pid, thread->owner_process->name);
- }
- else
- {
- log_write(LOG_CRITICAL, ", not attached to any process.\n");
- }
- }
- else
- {
- log_write(LOG_CRITICAL, "No context available.\n");
- }
- if (regs)
- {
- const char *flag_names[32] = {
- "CF", NULL, "PF", NULL, "AF", NULL, "ZF", "SF",
- "TF", "IF", "DF", "OF", NULL, NULL, "NT", NULL,
- "RF", "VM", "AC", "VIF", "VIP", "ID"
- };
- log_write(LOG_CRITICAL, "Machine state:\n");
- log_write(LOG_CRITICAL, "EAX: 0x%08X\n", regs->eax);
- log_write(LOG_CRITICAL, "ECX: 0x%08X\n", regs->ecx);
- log_write(LOG_CRITICAL, "EDX: 0x%08X\n", regs->edx);
- log_write(LOG_CRITICAL, "EBX: 0x%08X\n", regs->ebx);
- log_write(LOG_CRITICAL, "ESP: 0x%08X\n", regs->esp);
- log_write(LOG_CRITICAL, "EBP: 0x%08X\n", regs->ebp);
- log_write(LOG_CRITICAL, "ESI: 0x%08X\n", regs->eax);
- log_write(LOG_CRITICAL, "EDI: 0x%08X\n", regs->eax);
- log_write(LOG_CRITICAL, "EIP: 0x%08X\n", regs->eip);
- log_write(LOG_CRITICAL, "Code: 0x%04X\n", regs->cs);
- log_write(LOG_CRITICAL, "Data: 0x%04X\n", regs->data_selector);
- log_write(LOG_CRITICAL, "EFLAGS: %08X ( ", regs->eflags);
- for (i = 0; i < 32; i++)
- {
- if (flag_names[i] && regs->eflags & (1 << i))
- {
- log_write(LOG_CRITICAL, "%s ", flag_names[i]);
- }
- }
- log_write(LOG_CRITICAL, ")\n");
- log_write(LOG_CRITICAL, "CR0: 0x%08X\n", cpu_read_master_control_register());
- log_write(LOG_CRITICAL, "CR2: 0x%08X\n", cpu_read_faulting_address());
- log_write(LOG_CRITICAL, "CR3: 0x%08X\n", cpu_read_page_table_register());
- log_write(LOG_CRITICAL, "CR4: 0x%08X\n", cpu_read_feature_register());
- }
- else
- {
- log_write(LOG_CRITICAL, "No machine state available.\n");
- }
- log_write(LOG_CRITICAL, "Backtrace:\n");
- for (i = 0; i < call_count; i++)
- {
- log_write(LOG_CRITICAL, "0x%08X", call_stack[i]);
- module_t *module = get_module_from_address((void*)call_stack[i]);
- extern int _end;
- if (module)
- {
- log_write(LOG_CRITICAL, " in module %s", module->name);
- }
- else if (call_stack[i] >= KERNEL_AREA_START && call_stack[i] < (uintptr_t)&_end)
- {
- log_write(LOG_CRITICAL, " in the kernel");
- const char *function_name = lookup_kernel_symbol_name(call_stack[i]);
- if (function_name) log_write(LOG_CRITICAL, ", function %s", function_name);
- }
- log_write(LOG_CRITICAL, "\n");
- }
- cpu_halt();
- for(;;);
- }
|