mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
Kernel panics previously only stopped the calling core. This commit re-implements the panic system to allow us to stop all cores on a panic. Changes include: - panic now sends an NMI to all cores. This means we can't control the contents of their registers, so panic information has been moved to a global struct, and the panicking cpu sets the pointer to that data in its cpu_data. - the panic_handler is now set up with mutexes to print appropriately and only initialize objects once. - copying _current_gsbase into the panic handler, and #including the cpprt.cpp file (so that we can define NDEBUG and not have it try to link the assert code back in) - making the symbol data pointer in kargs an actual pointer again, not an address - and carrying that through to the panic handler - the number of cpus is now saved globally in the kernel as g_num_cpus
87 lines
2.0 KiB
C++
87 lines
2.0 KiB
C++
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "assert.h"
|
|
#include "cpu.h"
|
|
#include "cpu/cpu_id.h"
|
|
#include "device_manager.h"
|
|
#include "gdt.h"
|
|
#include "idt.h"
|
|
#include "log.h"
|
|
#include "msr.h"
|
|
#include "objects/vm_area.h"
|
|
#include "syscall.h"
|
|
#include "tss.h"
|
|
|
|
unsigned g_num_cpus = 1;
|
|
|
|
panic_data g_panic_data;
|
|
panic_data *g_panic_data_p = &g_panic_data;
|
|
|
|
cpu_data g_bsp_cpu_data;
|
|
|
|
void
|
|
cpu_validate()
|
|
{
|
|
cpu::cpu_id cpu;
|
|
|
|
log::info(logs::boot, "CPU: %s", cpu.brand_name());
|
|
log::debug(logs::boot, " Vendor is %s", cpu.vendor_id());
|
|
|
|
log::debug(logs::boot, " Higest basic CPUID: 0x%02x", cpu.highest_basic());
|
|
log::debug(logs::boot, " Higest ext CPUID: 0x%02x", cpu.highest_ext() & ~cpu::cpu_id::cpuid_extended);
|
|
|
|
#define CPU_FEATURE_OPT(name, ...) \
|
|
log::debug(logs::boot, " Supports %9s: %s", #name, cpu.has_feature(cpu::feature::name) ? "yes" : "no");
|
|
|
|
#define CPU_FEATURE_REQ(name, feat_leaf, feat_sub, regname, bit) \
|
|
CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit); \
|
|
kassert(cpu.has_feature(cpu::feature::name), "Missing required CPU feature " #name );
|
|
|
|
#include "cpu/features.inc"
|
|
#undef CPU_FEATURE_OPT
|
|
#undef CPU_FEATURE_REQ
|
|
}
|
|
|
|
void
|
|
global_cpu_init()
|
|
{
|
|
memset(&g_panic_data, 0, sizeof(g_panic_data));
|
|
}
|
|
|
|
void
|
|
cpu_early_init(cpu_data *cpu)
|
|
{
|
|
if (cpu->index == 0)
|
|
global_cpu_init();
|
|
|
|
cpu->idt->install();
|
|
cpu->gdt->install();
|
|
|
|
// Install the GS base pointint to the cpu_data
|
|
wrmsr(msr::ia32_gs_base, reinterpret_cast<uintptr_t>(cpu));
|
|
|
|
// Set the initial process as the kernel "process"
|
|
extern process &g_kernel_process;
|
|
cpu->process = &g_kernel_process;
|
|
}
|
|
|
|
void
|
|
cpu_init(cpu_data *cpu, bool bsp)
|
|
{
|
|
if (!bsp) {
|
|
// The BSP already called cpu_early_init
|
|
cpu_early_init(cpu);
|
|
}
|
|
|
|
// Set up the syscall MSRs
|
|
syscall_enable();
|
|
|
|
// Set up the page attributes table
|
|
uint64_t pat = rdmsr(msr::ia32_pat);
|
|
pat = (pat & 0x00ffffffffffffffull) | (0x01ull << 56); // set PAT 7 to WC
|
|
wrmsr(msr::ia32_pat, pat);
|
|
|
|
cpu->idt->add_ist_entries();
|
|
}
|