mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-31 16:38:12 +00:00
915fea04f9
The restart interrupt is triggered whenever a secondary CPU is brought online, a remote function call dispatched from another CPU or a manual PSW restart is initiated and causes the system to kdump. The handling routine is always called with DAT turned off. It then initializes the stack frame and invokes a callback. The existing callbacks handle DAT as follows: * __do_restart() and __machine_kexec() turn in on upon entry; * __ipl_run(), __reipl_run() and __dump_run() do not turn it right away, but all of them call diag308() - which turns DAT on, but only if kasan is enabled; In addition to the described complexity all callbacks (and the functions they call) should avoid kasan instrumentation while DAT is off. This update enables DAT in the assembler restart handler and relieves any callbacks (which are mostly C functions) from dealing with DAT altogether. There are four types of CPU restart that initialize control registers in different ways: 1. Start of secondary CPU on boot - control registers are inherited from the IPL CPU; 2. Restart of online CPU - control registers of the CPU being restarted are kept; 3. Hotplug of offline CPU - control registers are inherited from the starting CPU; 4. Start of offline CPU triggered by manual PSW restart - the control registers are read from the absolute lowcore and contain the boot time IPL CPU values updated with all follow-up calls of smp_ctl_set_bit() and smp_ctl_clear_bit() routines; In first three cases contents of the control registers is the most recent. In the latter case control registers are good enough to facilitate successful completion of kdump operation. Suggested-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
164 lines
7.2 KiB
C
164 lines
7.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Generate definitions needed by assembly language modules.
|
|
* This code generates raw asm output which is post-processed to extract
|
|
* and format the required data.
|
|
*/
|
|
|
|
#define ASM_OFFSETS_C
|
|
|
|
#include <linux/kbuild.h>
|
|
#include <linux/kvm_host.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/purgatory.h>
|
|
#include <linux/pgtable.h>
|
|
#include <asm/idle.h>
|
|
#include <asm/gmap.h>
|
|
#include <asm/stacktrace.h>
|
|
|
|
int main(void)
|
|
{
|
|
/* task struct offsets */
|
|
OFFSET(__TASK_stack, task_struct, stack);
|
|
OFFSET(__TASK_thread, task_struct, thread);
|
|
OFFSET(__TASK_pid, task_struct, pid);
|
|
BLANK();
|
|
/* thread struct offsets */
|
|
OFFSET(__THREAD_ksp, thread_struct, ksp);
|
|
BLANK();
|
|
/* thread info offsets */
|
|
OFFSET(__TI_flags, task_struct, thread_info.flags);
|
|
BLANK();
|
|
/* pt_regs offsets */
|
|
OFFSET(__PT_PSW, pt_regs, psw);
|
|
OFFSET(__PT_GPRS, pt_regs, gprs);
|
|
OFFSET(__PT_ORIG_GPR2, pt_regs, orig_gpr2);
|
|
OFFSET(__PT_FLAGS, pt_regs, flags);
|
|
OFFSET(__PT_CR1, pt_regs, cr1);
|
|
DEFINE(__PT_SIZE, sizeof(struct pt_regs));
|
|
BLANK();
|
|
/* stack_frame offsets */
|
|
OFFSET(__SF_BACKCHAIN, stack_frame, back_chain);
|
|
OFFSET(__SF_GPRS, stack_frame, gprs);
|
|
OFFSET(__SF_EMPTY, stack_frame, empty1[0]);
|
|
OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[1]);
|
|
OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[2]);
|
|
OFFSET(__SF_SIE_REASON, stack_frame, empty1[3]);
|
|
OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[4]);
|
|
BLANK();
|
|
/* idle data offsets */
|
|
OFFSET(__CLOCK_IDLE_ENTER, s390_idle_data, clock_idle_enter);
|
|
OFFSET(__CLOCK_IDLE_EXIT, s390_idle_data, clock_idle_exit);
|
|
OFFSET(__TIMER_IDLE_ENTER, s390_idle_data, timer_idle_enter);
|
|
OFFSET(__TIMER_IDLE_EXIT, s390_idle_data, timer_idle_exit);
|
|
OFFSET(__MT_CYCLES_ENTER, s390_idle_data, mt_cycles_enter);
|
|
BLANK();
|
|
/* hardware defined lowcore locations 0x000 - 0x1ff */
|
|
OFFSET(__LC_EXT_PARAMS, lowcore, ext_params);
|
|
OFFSET(__LC_EXT_CPU_ADDR, lowcore, ext_cpu_addr);
|
|
OFFSET(__LC_EXT_INT_CODE, lowcore, ext_int_code);
|
|
OFFSET(__LC_PGM_ILC, lowcore, pgm_ilc);
|
|
OFFSET(__LC_PGM_INT_CODE, lowcore, pgm_code);
|
|
OFFSET(__LC_DATA_EXC_CODE, lowcore, data_exc_code);
|
|
OFFSET(__LC_MON_CLASS_NR, lowcore, mon_class_num);
|
|
OFFSET(__LC_PER_CODE, lowcore, per_code);
|
|
OFFSET(__LC_PER_ATMID, lowcore, per_atmid);
|
|
OFFSET(__LC_PER_ADDRESS, lowcore, per_address);
|
|
OFFSET(__LC_EXC_ACCESS_ID, lowcore, exc_access_id);
|
|
OFFSET(__LC_PER_ACCESS_ID, lowcore, per_access_id);
|
|
OFFSET(__LC_OP_ACCESS_ID, lowcore, op_access_id);
|
|
OFFSET(__LC_AR_MODE_ID, lowcore, ar_mode_id);
|
|
OFFSET(__LC_TRANS_EXC_CODE, lowcore, trans_exc_code);
|
|
OFFSET(__LC_MON_CODE, lowcore, monitor_code);
|
|
OFFSET(__LC_SUBCHANNEL_ID, lowcore, subchannel_id);
|
|
OFFSET(__LC_SUBCHANNEL_NR, lowcore, subchannel_nr);
|
|
OFFSET(__LC_IO_INT_PARM, lowcore, io_int_parm);
|
|
OFFSET(__LC_IO_INT_WORD, lowcore, io_int_word);
|
|
OFFSET(__LC_MCCK_CODE, lowcore, mcck_interruption_code);
|
|
OFFSET(__LC_EXT_DAMAGE_CODE, lowcore, external_damage_code);
|
|
OFFSET(__LC_MCCK_FAIL_STOR_ADDR, lowcore, failing_storage_address);
|
|
OFFSET(__LC_LAST_BREAK, lowcore, breaking_event_addr);
|
|
OFFSET(__LC_RETURN_LPSWE, lowcore, return_lpswe);
|
|
OFFSET(__LC_RETURN_MCCK_LPSWE, lowcore, return_mcck_lpswe);
|
|
OFFSET(__LC_RST_OLD_PSW, lowcore, restart_old_psw);
|
|
OFFSET(__LC_EXT_OLD_PSW, lowcore, external_old_psw);
|
|
OFFSET(__LC_SVC_OLD_PSW, lowcore, svc_old_psw);
|
|
OFFSET(__LC_PGM_OLD_PSW, lowcore, program_old_psw);
|
|
OFFSET(__LC_MCK_OLD_PSW, lowcore, mcck_old_psw);
|
|
OFFSET(__LC_IO_OLD_PSW, lowcore, io_old_psw);
|
|
OFFSET(__LC_RST_NEW_PSW, lowcore, restart_psw);
|
|
OFFSET(__LC_EXT_NEW_PSW, lowcore, external_new_psw);
|
|
OFFSET(__LC_SVC_NEW_PSW, lowcore, svc_new_psw);
|
|
OFFSET(__LC_PGM_NEW_PSW, lowcore, program_new_psw);
|
|
OFFSET(__LC_MCK_NEW_PSW, lowcore, mcck_new_psw);
|
|
OFFSET(__LC_IO_NEW_PSW, lowcore, io_new_psw);
|
|
/* software defined lowcore locations 0x200 - 0xdff*/
|
|
OFFSET(__LC_SAVE_AREA_SYNC, lowcore, save_area_sync);
|
|
OFFSET(__LC_SAVE_AREA_ASYNC, lowcore, save_area_async);
|
|
OFFSET(__LC_SAVE_AREA_RESTART, lowcore, save_area_restart);
|
|
OFFSET(__LC_CPU_FLAGS, lowcore, cpu_flags);
|
|
OFFSET(__LC_RETURN_PSW, lowcore, return_psw);
|
|
OFFSET(__LC_RETURN_MCCK_PSW, lowcore, return_mcck_psw);
|
|
OFFSET(__LC_SYS_ENTER_TIMER, lowcore, sys_enter_timer);
|
|
OFFSET(__LC_MCCK_ENTER_TIMER, lowcore, mcck_enter_timer);
|
|
OFFSET(__LC_EXIT_TIMER, lowcore, exit_timer);
|
|
OFFSET(__LC_LAST_UPDATE_TIMER, lowcore, last_update_timer);
|
|
OFFSET(__LC_LAST_UPDATE_CLOCK, lowcore, last_update_clock);
|
|
OFFSET(__LC_INT_CLOCK, lowcore, int_clock);
|
|
OFFSET(__LC_MCCK_CLOCK, lowcore, mcck_clock);
|
|
OFFSET(__LC_BOOT_CLOCK, lowcore, boot_clock);
|
|
OFFSET(__LC_CURRENT, lowcore, current_task);
|
|
OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack);
|
|
OFFSET(__LC_ASYNC_STACK, lowcore, async_stack);
|
|
OFFSET(__LC_NODAT_STACK, lowcore, nodat_stack);
|
|
OFFSET(__LC_RESTART_STACK, lowcore, restart_stack);
|
|
OFFSET(__LC_MCCK_STACK, lowcore, mcck_stack);
|
|
OFFSET(__LC_RESTART_FN, lowcore, restart_fn);
|
|
OFFSET(__LC_RESTART_DATA, lowcore, restart_data);
|
|
OFFSET(__LC_RESTART_SOURCE, lowcore, restart_source);
|
|
OFFSET(__LC_RESTART_FLAGS, lowcore, restart_flags);
|
|
OFFSET(__LC_KERNEL_ASCE, lowcore, kernel_asce);
|
|
OFFSET(__LC_USER_ASCE, lowcore, user_asce);
|
|
OFFSET(__LC_LPP, lowcore, lpp);
|
|
OFFSET(__LC_CURRENT_PID, lowcore, current_pid);
|
|
OFFSET(__LC_PERCPU_OFFSET, lowcore, percpu_offset);
|
|
OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
|
|
OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
|
|
OFFSET(__LC_GMAP, lowcore, gmap);
|
|
OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline);
|
|
/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
|
|
OFFSET(__LC_DUMP_REIPL, lowcore, ipib);
|
|
/* hardware defined lowcore locations 0x1000 - 0x18ff */
|
|
OFFSET(__LC_MCESAD, lowcore, mcesad);
|
|
OFFSET(__LC_EXT_PARAMS2, lowcore, ext_params2);
|
|
OFFSET(__LC_FPREGS_SAVE_AREA, lowcore, floating_pt_save_area);
|
|
OFFSET(__LC_GPREGS_SAVE_AREA, lowcore, gpregs_save_area);
|
|
OFFSET(__LC_PSW_SAVE_AREA, lowcore, psw_save_area);
|
|
OFFSET(__LC_PREFIX_SAVE_AREA, lowcore, prefixreg_save_area);
|
|
OFFSET(__LC_FP_CREG_SAVE_AREA, lowcore, fpt_creg_save_area);
|
|
OFFSET(__LC_TOD_PROGREG_SAVE_AREA, lowcore, tod_progreg_save_area);
|
|
OFFSET(__LC_CPU_TIMER_SAVE_AREA, lowcore, cpu_timer_save_area);
|
|
OFFSET(__LC_CLOCK_COMP_SAVE_AREA, lowcore, clock_comp_save_area);
|
|
OFFSET(__LC_AREGS_SAVE_AREA, lowcore, access_regs_save_area);
|
|
OFFSET(__LC_CREGS_SAVE_AREA, lowcore, cregs_save_area);
|
|
OFFSET(__LC_PGM_TDB, lowcore, pgm_tdb);
|
|
BLANK();
|
|
/* gmap/sie offsets */
|
|
OFFSET(__GMAP_ASCE, gmap, asce);
|
|
OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c);
|
|
OFFSET(__SIE_PROG20, kvm_s390_sie_block, prog20);
|
|
/* kexec_sha_region */
|
|
OFFSET(__KEXEC_SHA_REGION_START, kexec_sha_region, start);
|
|
OFFSET(__KEXEC_SHA_REGION_LEN, kexec_sha_region, len);
|
|
DEFINE(__KEXEC_SHA_REGION_SIZE, sizeof(struct kexec_sha_region));
|
|
/* sizeof kernel parameter area */
|
|
DEFINE(__PARMAREA_SIZE, sizeof(struct parmarea));
|
|
/* kernel parameter area offsets */
|
|
DEFINE(IPL_DEVICE, PARMAREA + offsetof(struct parmarea, ipl_device));
|
|
DEFINE(INITRD_START, PARMAREA + offsetof(struct parmarea, initrd_start));
|
|
DEFINE(INITRD_SIZE, PARMAREA + offsetof(struct parmarea, initrd_size));
|
|
DEFINE(OLDMEM_BASE, PARMAREA + offsetof(struct parmarea, oldmem_base));
|
|
DEFINE(OLDMEM_SIZE, PARMAREA + offsetof(struct parmarea, oldmem_size));
|
|
DEFINE(COMMAND_LINE, PARMAREA + offsetof(struct parmarea, command_line));
|
|
return 0;
|
|
}
|