/* * Reset the system, copy boot CPU registers to absolute zero, * and jump to the kdump image
*/ staticvoid __do_machine_kdump(void *data)
{ struct kimage *image = data;
purgatory_t purgatory; unsignedlong prefix;
purgatory = (purgatory_t)image->start;
/* store_status() saved the prefix register to lowcore */
prefix = (unsignedlong)get_lowcore()->prefixreg_save_area;
/* Now do the reset */
s390_reset_system();
/* * Copy dump CPU store status info to absolute zero. * This need to be done *after* s390_reset_system set the * prefix register of this CPU to zero
*/
memcpy(absolute_pointer(get_lowcore()->floating_pt_save_area),
phys_to_virt(prefix + __LC_FPREGS_SAVE_AREA), 512);
call_nodat(1, int, purgatory, int, 1);
/* Die if kdump returns */
disabled_wait();
}
/* * Start kdump: create a LGR log entry, store status of all CPUs and * branch to __do_machine_kdump.
*/ static noinline void __machine_kdump(void *image)
{ struct mcesa *mcesa; union ctlreg2 cr2_old, cr2_new; int this_cpu, cpu;
lgr_info_log(); /* Get status of the other CPUs */
this_cpu = smp_find_processor_id(stap());
for_each_online_cpu(cpu) { if (cpu == this_cpu) continue; if (smp_store_status(cpu)) continue;
} /* Store status of the boot CPU */
mcesa = __va(get_lowcore()->mcesad & MCESA_ORIGIN_MASK); if (cpu_has_vx())
save_vx_regs((__vector128 *) mcesa->vector_save_area); if (cpu_has_gs()) {
local_ctl_store(2, &cr2_old.reg);
cr2_new = cr2_old;
cr2_new.gse = 1;
local_ctl_load(2, &cr2_new.reg);
save_gs_cb((struct gs_cb *) mcesa->guarded_storage_save_area);
local_ctl_load(2, &cr2_old.reg);
} /* * To create a good backchain for this CPU in the dump store_status * is passed the address of a function. The address is saved into * the PSW save area of the boot CPU and the function is invoked as * a tail call of store_status. The backchain in the dump will look * like this: * restart_int_handler -> __machine_kexec -> __do_machine_kdump * The call to store_status() will not return.
*/
store_status(__do_machine_kdump, image);
}
#endif/* CONFIG_CRASH_DUMP */
/* * Check if kdump checksums are valid: We call purgatory with parameter "0"
*/ staticbool kdump_csum_valid(struct kimage *image)
{ #ifdef CONFIG_CRASH_DUMP
purgatory_t purgatory = (purgatory_t)image->start; int rc;
/* * Give back memory to hypervisor before new kdump is loaded
*/ staticint machine_kexec_prepare_kdump(void)
{ #ifdef CONFIG_CRASH_DUMP if (machine_is_vm())
diag10_range(PFN_DOWN(crashk_res.start),
PFN_DOWN(crashk_res.end - crashk_res.start + 1)); return 0; #else return -EINVAL; #endif
}
int machine_kexec_prepare(struct kimage *image)
{ void *reboot_code_buffer;
if (image->type == KEXEC_TYPE_CRASH) return machine_kexec_prepare_kdump();
/* We don't support anything but the default image type for now. */ if (image->type != KEXEC_TYPE_DEFAULT) return -EINVAL;
/* Get the destination where the assembler code should be copied to.*/
reboot_code_buffer = page_to_virt(image->control_code_page);
/* Then copy it */
memcpy(reboot_code_buffer, relocate_kernel, relocate_kernel_len); return 0;
}
/* * Reset system and call either kdump or normal kexec
*/ staticvoid __machine_kexec(void *data)
{
pfault_fini();
tracing_off();
debug_locks_off(); #ifdef CONFIG_CRASH_DUMP if (((struct kimage *) data)->type == KEXEC_TYPE_CRASH)
__machine_kdump(data); #endif
__do_machine_kexec(data);
}
/* * Do either kdump or normal kexec. In case of kdump we first ask * purgatory, if kdump checksums are valid.
*/ void machine_kexec(struct kimage *image)
{ if (image->type == KEXEC_TYPE_CRASH && !kdump_csum_valid(image)) return;
tracer_disable();
smp_send_stop();
smp_call_ipl_cpu(__machine_kexec, image);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.29 Sekunden
(vorverarbeitet)
¤
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.