void segfault_handler(unsigned int address, unsigned int write, PROCESSOR_DATA_BLOCK *hvcontext) { // This is called when a program segfaults // If write = 1, it tried to write to the address PROCESSOR_DATA_BLOCK *processor = thread_get_processor_block(); // Local stack context CONTEXT context; // If the exception was handled unsigned int handled = 0; // If we are first entering this handler unsigned int recursionCheck = 1; // Make sure only one exception gets in at a time if(processor->ExceptionRecursion == 0) lock(&program_interrupt_lock); else recursionCheck = 0; processor->ExceptionRecursion = 1; // Save the context dump_thread_context(&context); memcpy(context.Gpr, hvcontext->RegisterSave, 32*8); context.Cr = hvcontext->CRSave; context.Ctr = hvcontext->CTRSave; context.Iar = hvcontext->IARSave; context.Lr = hvcontext->LRSave; context.Msr = hvcontext->MSRSave; context.Xer = hvcontext->XERSave; // Adjust the context pointer mtsprg1(mfsprg1() - 0x200); processor->DAR = address; unsigned int code = write ? EXCEPT_CODE_SEGMENTATION_FAULT_WRITE : EXCEPT_CODE_SEGMENTATION_FAULT_READ; // Dispatch if(debugRoutine) handled = debugRoutine(code, &context); // Crash dump if(handled == 0) dump_thread_context_to_screen(processor, code, &context); // Restore context restore_thread_context(&context); processor->ExceptionRecursion = 0; if(recursionCheck) unlock(&program_interrupt_lock); }
void save_sprs(struct vcpu *v) { v->arch.timebase = mftb(); v->arch.sprg[0] = mfsprg0(); v->arch.sprg[1] = mfsprg1(); v->arch.sprg[2] = mfsprg2(); v->arch.sprg[3] = mfsprg3(); v->arch.dar = mfdar(); v->arch.dsisr = mfdsisr(); if (v->arch.pmu_enabled) { save_pmc_sprs(&(v->arch.perf_sprs)); v->arch.perf_sprs_stored = 1; } save_cpu_sprs(v); }