/* * Called when the CPU is to be halted. It will choose the best C-State * to be in. */ void pmCPUHalt(uint32_t reason) { cpu_data_t *cpup = current_cpu_datap(); switch (reason) { case PM_HALT_DEBUG: cpup->lcpu.state = LCPU_PAUSE; pal_stop_cpu(FALSE); break; case PM_HALT_PANIC: cpup->lcpu.state = LCPU_PAUSE; pal_stop_cpu(TRUE); break; case PM_HALT_NORMAL: case PM_HALT_SLEEP: default: pal_cli(); if (pmInitDone && pmDispatch != NULL && pmDispatch->pmCPUHalt != NULL) { /* * Halt the CPU (and put it in a low power state. */ (*pmDispatch->pmCPUHalt)(); /* * We've exited halt, so get the CPU schedulable again. * - by calling the fast init routine for a slave, or * - by returning if we're the master processor. */ if (cpup->cpu_number != master_cpu) { i386_init_slave_fast(); panic("init_slave_fast returned"); } } else { /* * If no power managment and a processor is taken off-line, * then invalidate the cache and halt it (it will not be able * to be brought back on-line without resetting the CPU). */ __asm__ volatile ("wbinvd"); cpup->lcpu.state = LCPU_HALT; pal_stop_cpu(FALSE); panic("back from Halt"); } break; } }
void panic(const char *errormsg, ...) { va_list list; kprintf("\nKERNEL PANIC: "); if (can_use_serial) { bool early = false; if (rdmsr64(MSR_IA32_GS_BASE) == 0 && enable == false) { early = true; } if (early) { va_start(list, errormsg); _doprnt_log(errormsg, &list, serial_putc, 16); va_end(list); goto panicing; } else { normal_print: va_start(list, errormsg); _doprnt(errormsg, &list, putc, 16); va_end(list); goto panicing; } } else { goto normal_print; } panicing: kprintf("\nCPU Halted"); pal_stop_cpu(true); }