Skip to content

Commit e7ec1d2

Browse files
Alexander Gordeevhcahca
authored andcommitted
s390/mcck: cleanup user process termination path
If a machine check interrupt hits while user process is running __s390_handle_mcck() helper function is called directly from the interrupt handler and terminates the current process by calling make_task_dead() routine. The make_task_dead() is not allowed to be called from interrupt context which forces the machine check handler switch to the kernel stack and enable local interrupts first. The __s390_handle_mcck() could also be called to service pending work, but this time from the external interrupts handler. It is the machine check handler that establishes the work and schedules the external interrupt, therefore the machine check interrupt itself should be disabled while reading out the corresponding variable: local_mcck_disable(); mcck = *this_cpu_ptr(&cpu_mcck); memset(this_cpu_ptr(&cpu_mcck), 0, sizeof(mcck)); local_mcck_enable(); However, local_mcck_disable() does not have effect when __s390_handle_mcck() is called directly form the machine check handler, since the machine check interrupt is still disabled. Therefore, it is not the opening bracket to the following local_mcck_enable() function. Simplify the user process termination flow by scheduling the external interrupt and killing the affected process from the interrupt context. Assume a kernel-generated signal is always delivered and ignore a value returned by do_send_sig_info() funciton. Reviewed-by: Heiko Carstens <[email protected]> Reviewed-by: Sven Schnelle <[email protected]> Signed-off-by: Alexander Gordeev <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent 5e02c74 commit e7ec1d2

File tree

4 files changed

+8
-32
lines changed

4 files changed

+8
-32
lines changed

arch/s390/include/asm/nmi.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,8 @@ void nmi_alloc_mcesa_early(u64 *mcesad);
101101
int nmi_alloc_mcesa(u64 *mcesad);
102102
void nmi_free_mcesa(u64 *mcesad);
103103

104-
void s390_handle_mcck(struct pt_regs *regs);
105-
void __s390_handle_mcck(void);
106-
int s390_do_machine_check(struct pt_regs *regs);
104+
void s390_handle_mcck(void);
105+
void s390_do_machine_check(struct pt_regs *regs);
107106

108107
#endif /* __ASSEMBLY__ */
109108
#endif /* _ASM_S390_NMI_H */

arch/s390/kernel/entry.S

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -562,16 +562,6 @@ ENTRY(mcck_int_handler)
562562
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
563563
lgr %r2,%r11 # pass pointer to pt_regs
564564
brasl %r14,s390_do_machine_check
565-
cghi %r2,0
566-
je .Lmcck_return
567-
lg %r1,__LC_KERNEL_STACK # switch to kernel stack
568-
mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
569-
xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
570-
la %r11,STACK_FRAME_OVERHEAD(%r1)
571-
lgr %r2,%r11
572-
lgr %r15,%r1
573-
brasl %r14,s390_handle_mcck
574-
.Lmcck_return:
575565
lctlg %c1,%c1,__PT_CR1(%r11)
576566
lmg %r0,%r10,__PT_R0(%r11)
577567
mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW

arch/s390/kernel/nmi.c

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ NOKPROBE_SYMBOL(s390_handle_damage);
156156
* Main machine check handler function. Will be called with interrupts disabled
157157
* and machine checks enabled.
158158
*/
159-
void __s390_handle_mcck(void)
159+
void s390_handle_mcck(void)
160160
{
161161
struct mcck_struct mcck;
162162

@@ -192,23 +192,16 @@ void __s390_handle_mcck(void)
192192
if (mcck.stp_queue)
193193
stp_queue_work();
194194
if (mcck.kill_task) {
195-
local_irq_enable();
196195
printk(KERN_EMERG "mcck: Terminating task because of machine "
197196
"malfunction (code 0x%016lx).\n", mcck.mcck_code);
198197
printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
199198
current->comm, current->pid);
200-
make_task_dead(SIGSEGV);
199+
if (is_global_init(current))
200+
panic("mcck: Attempting to kill init!\n");
201+
do_send_sig_info(SIGKILL, SEND_SIG_PRIV, current, PIDTYPE_PID);
201202
}
202203
}
203204

204-
void noinstr s390_handle_mcck(struct pt_regs *regs)
205-
{
206-
trace_hardirqs_off();
207-
pai_kernel_enter(regs);
208-
__s390_handle_mcck();
209-
pai_kernel_exit(regs);
210-
trace_hardirqs_on();
211-
}
212205
/*
213206
* returns 0 if register contents could be validated
214207
* returns 1 otherwise
@@ -373,7 +366,7 @@ NOKPROBE_SYMBOL(s390_backup_mcck_info);
373366
/*
374367
* machine check handler.
375368
*/
376-
int notrace s390_do_machine_check(struct pt_regs *regs)
369+
void notrace s390_do_machine_check(struct pt_regs *regs)
377370
{
378371
static int ipd_count;
379372
static DEFINE_SPINLOCK(ipd_lock);
@@ -503,16 +496,10 @@ int notrace s390_do_machine_check(struct pt_regs *regs)
503496
}
504497
clear_cpu_flag(CIF_MCCK_GUEST);
505498

506-
if (user_mode(regs) && mcck_pending) {
507-
irqentry_nmi_exit(regs, irq_state);
508-
return 1;
509-
}
510-
511499
if (mcck_pending)
512500
schedule_mcck_handler();
513501

514502
irqentry_nmi_exit(regs, irq_state);
515-
return 0;
516503
}
517504
NOKPROBE_SYMBOL(s390_do_machine_check);
518505

arch/s390/kernel/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ static void smp_handle_ext_call(void)
522522
if (test_bit(ec_call_function_single, &bits))
523523
generic_smp_call_function_single_interrupt();
524524
if (test_bit(ec_mcck_pending, &bits))
525-
__s390_handle_mcck();
525+
s390_handle_mcck();
526526
if (test_bit(ec_irq_work, &bits))
527527
irq_work_run();
528528
}

0 commit comments

Comments
 (0)