mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 15:27:29 +00:00
s390/dump: rework CPU register dump code
To collect the CPU registers of the crashed system allocated a single page with memblock_alloc_base and use it as a copy buffer. Replace the stop-and-store-status sigp with a store-status-at-address sigp in smp_save_dump_cpus() and smp_store_status(). In both cases the target CPU is already stopped and store-status-at-address avoids the detour via the absolute zero page. For kexec simplify s390_reset_system and call store_status() before the prefix register of the boot CPU has been set to zero. Use STPX to store the prefix register and remove dump_prefix_page. Acked-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
f08b841463
commit
1a36a39e22
12 changed files with 158 additions and 145 deletions
|
@ -34,40 +34,6 @@ extern const unsigned long long relocate_kernel_len;
|
|||
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
|
||||
/*
|
||||
* Initialize CPU ELF notes
|
||||
*/
|
||||
static void setup_regs(void)
|
||||
{
|
||||
struct save_area *sa, *sa_0;
|
||||
unsigned long prefix;
|
||||
int cpu, this_cpu;
|
||||
|
||||
/* setup_regs is called with the prefix register = 0 */
|
||||
sa_0 = (struct save_area *) __LC_FPREGS_SAVE_AREA;
|
||||
|
||||
/* Get status of this CPU out of absolute zero */
|
||||
prefix = (unsigned long) S390_lowcore.prefixreg_save_area;
|
||||
sa = (struct save_area *)(prefix + __LC_FPREGS_SAVE_AREA);
|
||||
memcpy(sa, sa_0, sizeof(struct save_area));
|
||||
if (MACHINE_HAS_VX) {
|
||||
struct _lowcore *lc = (struct _lowcore *) prefix;
|
||||
save_vx_regs_safe((void *) lc->vector_save_area_addr);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
prefix = (unsigned long) S390_lowcore.prefixreg_save_area;
|
||||
sa = (struct save_area *)(prefix + __LC_FPREGS_SAVE_AREA);
|
||||
memcpy(sa, sa_0, sizeof(struct save_area));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PM notifier callback for kdump
|
||||
*/
|
||||
|
@ -99,14 +65,66 @@ static int __init machine_kdump_pm_init(void)
|
|||
arch_initcall(machine_kdump_pm_init);
|
||||
|
||||
/*
|
||||
* Start kdump: We expect here that a store status has been done on our CPU
|
||||
* Reset the system, copy boot CPU registers to absolute zero,
|
||||
* and jump to the kdump image
|
||||
*/
|
||||
static void __do_machine_kdump(void *image)
|
||||
{
|
||||
int (*start_kdump)(int) = (void *)((struct kimage *) image)->start;
|
||||
int (*start_kdump)(int);
|
||||
unsigned long prefix;
|
||||
|
||||
/* store_status() saved the prefix register to lowcore */
|
||||
prefix = (unsigned long) S390_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((void *) __LC_FPREGS_SAVE_AREA,
|
||||
(void *)(prefix + __LC_FPREGS_SAVE_AREA), 512);
|
||||
|
||||
__load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
|
||||
start_kdump = (void *)((struct kimage *) image)->start;
|
||||
start_kdump(1);
|
||||
|
||||
/* Die if start_kdump returns */
|
||||
disabled_wait((unsigned long) __builtin_return_address(0));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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 */
|
||||
if (MACHINE_HAS_VX)
|
||||
save_vx_regs((void *) &S390_lowcore.vector_save_area);
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
@ -229,10 +247,14 @@ static void __do_machine_kexec(void *data)
|
|||
relocate_kernel_t data_mover;
|
||||
struct kimage *image = data;
|
||||
|
||||
s390_reset_system();
|
||||
data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page);
|
||||
|
||||
/* Call the moving routine */
|
||||
(*data_mover)(&image->head, image->start);
|
||||
|
||||
/* Die if kexec returns */
|
||||
disabled_wait((unsigned long) __builtin_return_address(0));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -245,14 +267,10 @@ static void __machine_kexec(void *data)
|
|||
tracing_off();
|
||||
debug_locks_off();
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
if (((struct kimage *) data)->type == KEXEC_TYPE_CRASH) {
|
||||
|
||||
lgr_info_log();
|
||||
s390_reset_system(setup_regs, __do_machine_kdump, data);
|
||||
} else
|
||||
if (((struct kimage *) data)->type == KEXEC_TYPE_CRASH)
|
||||
__machine_kdump(data);
|
||||
#endif
|
||||
s390_reset_system(NULL, __do_machine_kexec, data);
|
||||
disabled_wait((unsigned long) __builtin_return_address(0));
|
||||
__do_machine_kexec(data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue