/* Find the command line */ for (i = 0; i < kimage->nr_segments; i++) { if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) { if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
kimage->arch.cmdline_ptr = (unsignedlong)cmdline_ptr; break;
}
}
if (!kimage->arch.cmdline_ptr) {
pr_err("Command line not included in the provided image\n"); return -EINVAL;
}
/* kexec/kdump need a safe page to save reboot_code_buffer */
kimage->control_code_page = virt_to_page((void *)KEXEC_CONTROL_CODE);
/* * We know we were online, and there will be no incoming IPIs at * this point. Mark online again before rebooting so that the crash * analysis tool will see us correctly.
*/
set_cpu_online(smp_processor_id(), true);
/* Ensure remote CPUs observe that we're online before rebooting. */
smp_mb__after_atomic();
/* * Make sure we get correct instructions written by the * machine_kexec_prepare() CPU.
*/
__asm__ __volatile__ ("\tibar 0\n"::);
#ifdef CONFIG_SMP /* All secondary cpus go to kexec_smp_wait */ if (smp_processor_id() > 0) {
relocated_kexec_smp_wait(NULL);
BUG();
} #endif
#ifdef CONFIG_SMP staticvoid kexec_shutdown_secondary(void *regs)
{ int cpu = smp_processor_id();
if (!cpu_online(cpu)) return;
/* We won't be sent IPIs any more. */
set_cpu_online(cpu, false);
local_irq_disable(); while (!atomic_read(&kexec_ready_to_reboot))
cpu_relax();
kexec_reboot();
}
staticvoid crash_shutdown_secondary(void *passed_regs)
{ int cpu = smp_processor_id(); struct pt_regs *regs = passed_regs;
/* * If we are passed registers, use those. Otherwise get the * regs from the last interrupt, which should be correct, as * we are in an interrupt. But if the regs are not there, * pull them from the top of the stack. They are probably * wrong, but we need something to keep from crashing again.
*/ if (!regs)
regs = get_irq_regs(); if (!regs)
regs = task_pt_regs(current);
if (!cpu_online(cpu)) return;
/* We won't be sent IPIs any more. */
set_cpu_online(cpu, false);
local_irq_disable(); if (!cpumask_test_cpu(cpu, &cpus_in_crash))
crash_save_cpu(regs, cpu);
cpumask_set_cpu(cpu, &cpus_in_crash);
while (!atomic_read(&kexec_ready_to_reboot))
cpu_relax();
/* * The crash CPU sends an IPI and wait for other CPUs to * respond. Delay of at least 10 seconds.
*/
timeout = MSEC_PER_SEC * 10;
pr_emerg("Sending IPI to other cpus...\n"); while ((cpumask_weight(&cpus_in_crash) < ncpus) && timeout--) {
mdelay(1);
cpu_relax();
}
} #endif/* defined(CONFIG_SMP) */
void machine_shutdown(void)
{ #ifdef CONFIG_SMP int cpu;
/* All CPUs go to reboot_code_buffer */
for_each_possible_cpu(cpu) if (!cpu_online(cpu))
cpu_device_up(get_cpu_device(cpu));
/* * The generic kexec code builds a page list with physical * addresses. they are directly accessible through XKPRANGE * hence the phys_to_virt() call.
*/ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
ptr = (entry & IND_INDIRECTION) ?
phys_to_virt(entry & PAGE_MASK) : ptr + 1) { if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
*ptr & IND_DESTINATION)
*ptr = (unsignedlong) phys_to_virt(*ptr);
}
/* Mark offline before disabling local irq. */
set_cpu_online(smp_processor_id(), false);
/* We do not want to be bothered. */
local_irq_disable();
pr_notice("EFI boot flag 0x%lx\n", efi_boot);
pr_notice("Command line at 0x%lx\n", cmdline_ptr);
pr_notice("System table at 0x%lx\n", systable_ptr);
pr_notice("We will call new kernel at 0x%lx\n", start_addr);
pr_notice("Bye ...\n");
/* Make reboot code buffer available to the boot CPU. */
flush_cache_all();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.