From patchwork Mon Dec 19 18:30:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 707182 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tj8n91JXFz9t37 for ; Tue, 20 Dec 2016 05:38:21 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="S3URIapZ"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3tj8n90BNFzDwtl for ; Tue, 20 Dec 2016 05:38:21 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="S3URIapZ"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from mail-pf0-x243.google.com (mail-pf0-x243.google.com [IPv6:2607:f8b0:400e:c00::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3tj8cD0nQBzDwQ5 for ; Tue, 20 Dec 2016 05:30:36 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="S3URIapZ"; dkim-atps=neutral Received: by mail-pf0-x243.google.com with SMTP id 144so7867916pfv.0 for ; Mon, 19 Dec 2016 10:30:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=coLFLe+cXbzIRrcsgrNT+3ctChfcrx1/KD2Z0UZ9qDw=; b=S3URIapZUKj83y7ZBtKi+UqoUGMX8Xe8CHgsVZuSuTLKbWz+hC55L2YHilEF5GOIcW ZsPQYyFO3MfMkme7Ea1d+WhoIMmN33nueblgtbtnZMWelrPUXlDLpdkVf5j01NT6lnKw ESu12XclCoNKQec4eqU/+iKp2DgRx1CpJKAAEtGN7jJkjV+u0lfJN8SoeYQB7vysfvvz bNf9bVqBCVxDF1ra58vJXhAae5d1vebKmb2D1GiC4pEm3reODUZS6V4+oHXb2x/v4m9y xixa7qx/3BaiWAXYQGQL6+jR52HCuk98QxaUrS8PfSJxg0e2mscvh9MvDv6iEip6IzRl j+xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=coLFLe+cXbzIRrcsgrNT+3ctChfcrx1/KD2Z0UZ9qDw=; b=QEYSUJ0knDbJ0FD3irk5FymXdAeJdhoBaC75T+Yj/znk+QTYV4dssJQqvLX/pzQ/lM 7z+abe0SInRdTrbe2jPKvAwWgTFuMnLwjIiJwTWmXEnVdEgGbtPHjoK/Za/cGvX4VHwt Oxkm8X+7vF5b3RSorAEdg9sxMwvZkAPr0Y4E57RIc/W1GKcFL1WFPHvtxwmEFVhEefir en/7mRdxEjm7cp0+0oICu6QBd6xujYsvV63uHvXmUejlJn/a/t0ZQyK1zo72ZZFI6GmB rgW1/+FZySh/zMRZLf7kGn3twm4J6wHkaqDNhJJwYkgUG8wKDNwt4CruL8MyS4IZ07U3 Jejw== X-Gm-Message-State: AKaTC00yuKQwpDx0U+arc9B3ZNczIJ29/jiDUqpiLPKon1YUE72tAPKMDtlj0y14p+5sgg== X-Received: by 10.84.213.144 with SMTP id g16mr37209440pli.134.1482172233601; Mon, 19 Dec 2016 10:30:33 -0800 (PST) Received: from roar.au.ibm.com ([61.68.124.232]) by smtp.gmail.com with ESMTPSA id g27sm33135147pfk.58.2016.12.19.10.30.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Dec 2016 10:30:33 -0800 (PST) From: Nicholas Piggin To: linuxppc-dev@lists.ozlabs.org Subject: [PATCH 04/10] powerpc/64s: disallow system reset vs system reset reentrancy Date: Tue, 20 Dec 2016 04:30:05 +1000 Message-Id: <20161219183011.28310-5-npiggin@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20161219183011.28310-1-npiggin@gmail.com> References: <20161219183011.28310-1-npiggin@gmail.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Nicholas Piggin Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" In preparation for using a dedicated stack for system reset interrupts, prevent a nested system reset from recovering, in order to simplify code that is called in crash/debug path. This allows a system reset interrupt to just use the base stack pointer. Keep an in_nmi nesting counter similarly to the in_mce counter. Consider the interrrupt non-recoverable if it is taken inside another system reset. Interrupt nesting could be allowed similarly to MCE, but system reset is a special case that's not for normal operation, so simplicity wins until there is requirement for nested system reset interrupts. Signed-off-by: Nicholas Piggin --- arch/powerpc/include/asm/exception-64s.h | 11 ++++++++++ arch/powerpc/include/asm/paca.h | 5 ++++- arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kernel/exceptions-64s.S | 37 +++++++++++++++++++++++++++----- arch/powerpc/kernel/traps.c | 8 ++++++- arch/powerpc/xmon/xmon.c | 1 + 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 18eceba135cb..7e47fb67c696 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -214,12 +214,23 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXCEPTION_PROLOG_1(area, extra, vec); \ EXCEPTION_PROLOG_PSERIES_1(label, h); +/* Do not enable RI */ +#define EXCEPTION_PROLOG_PSERIES_NORI(area, label, h, extra, vec) \ + EXCEPTION_PROLOG_0(area); \ + EXCEPTION_PROLOG_1(area, extra, vec); \ + EXCEPTION_PROLOG_PSERIES_1_NORI(label, h); + /* Have the PACA in r13 already */ #define EXCEPTION_PROLOG_PSERIES_PACA(area, label, h, extra, vec) \ EXCEPTION_PROLOG_0_PACA(area); \ EXCEPTION_PROLOG_1(area, extra, vec); \ EXCEPTION_PROLOG_PSERIES_1(label, h); +#define EXCEPTION_PROLOG_PSERIES_PACA_NORI(area, label, h, extra, vec) \ + EXCEPTION_PROLOG_0_PACA(area); \ + EXCEPTION_PROLOG_1(area, extra, vec); \ + EXCEPTION_PROLOG_PSERIES_1_NORI(label, h); + #define __KVMTEST(h, n) \ lbz r10,HSTATE_IN_GUEST(r13); \ cmpwi r10,0; \ diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 06e96648c1cb..98da152b257b 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -181,12 +181,15 @@ struct paca_struct { #ifdef CONFIG_PPC_BOOK3S_64 /* Exclusive emergency stack pointer for machine check exception. */ void *mc_emergency_sp; + + u16 in_nmi; /* In nmi handler */ + /* * Flag to check whether we are in machine check early handler * and already using emergency stack. */ u16 in_mce; - u8 hmi_event_available; /* HMI event is available */ + u8 hmi_event_available; /* HMI event is available */ #endif /* Stuff for accurate time accounting */ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index fa7087a2d825..893da286ecc3 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -244,6 +244,7 @@ int main(void) #ifdef CONFIG_PPC_BOOK3S_64 DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp)); DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce)); + DEFINE(PACA_IN_NMI, offsetof(struct paca_struct, in_nmi)); #endif DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index dd2bb0d785c6..4034f7db73b7 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -118,7 +118,11 @@ EXC_REAL_BEGIN(system_reset, 0x100, 0x200) SET_SCRATCH0(r13) GET_PACA(r13) clrrdi r13,r13,1 /* Last bit of HSPRG0 is set if waking from winkle */ - EXCEPTION_PROLOG_PSERIES_PACA(PACA_EXNMI, system_reset_common, + /* + * MSR_RI is not enabled, because PACA_EXNMI and nmi stack is + * being used, so a nested NMI exception would corrupt it. + */ + EXCEPTION_PROLOG_PSERIES_PACA_NORI(PACA_EXNMI, system_reset_common, EXC_STD, IDLETEST, 0x100) EXC_REAL_END(system_reset, 0x100, 0x200) @@ -154,9 +158,31 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) #endif EXC_COMMON_BEGIN(system_reset_common) + /* + * Increment paca->in_nmi then enable MSR_RI. SLB or MCE will be able + * to recover, but nested NMI will notice in_nmi and not recover + * because of the use of the NMI stack. in_nmi reentrancy is tested in + * system_reset_exception. + */ + lhz r10,PACA_IN_NMI(r13) + addi r10,r10,1 + sth r10,PACA_IN_NMI(r13) + li r10,MSR_RI + mtmsrd r10,1 + EXCEPTION_COMMON(PACA_EXNMI, 0x100, - system_reset, system_reset_exception, - ret_from_except, ADD_NVGPRS;ADD_RECONCILE) + system_reset, system_reset_exception, 1f, + ADD_NVGPRS;ADD_RECONCILE) +1: /* EXCEPTION_COMMON continues here */ + + /* + * The stack is no longer in use, decrement in_nmi. + */ + lhz r10,PACA_IN_NMI(r13) + subi r10,r10,1 + sth r10,PACA_IN_NMI(r13) + + b ret_from_except #ifdef CONFIG_PPC_PSERIES /* @@ -164,8 +190,9 @@ EXC_COMMON_BEGIN(system_reset_common) */ TRAMP_REAL_BEGIN(system_reset_fwnmi) SET_SCRATCH0(r13) /* save r13 */ - EXCEPTION_PROLOG_PSERIES(PACA_EXNMI, system_reset_common, EXC_STD, - NOTEST, 0x100) + /* See comment at system_reset exception */ + EXCEPTION_PROLOG_PSERIES_NORI(PACA_EXNMI, system_reset_common, + EXC_STD, NOTEST, 0x100) #endif /* CONFIG_PPC_PSERIES */ diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 4239aaf74886..802aa6bbe97b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -281,11 +281,17 @@ void system_reset_exception(struct pt_regs *regs) /* See if any machine dependent calls */ if (ppc_md.system_reset_exception) { if (ppc_md.system_reset_exception(regs)) - return; + goto out; } die("System Reset", regs, SIGABRT); +out: +#ifdef CONFIG_PPC_BOOK3S_64 + BUG_ON(get_paca()->in_nmi == 0); + if (get_paca()->in_nmi > 1) + panic("Unrecoverable nested System Reset"); +#endif /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable System Reset"); diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 9c0e17cf6886..832cbc097416 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2228,6 +2228,7 @@ static void dump_one_paca(int cpu) DUMP(p, emergency_sp, "p"); #ifdef CONFIG_PPC_BOOK3S_64 DUMP(p, mc_emergency_sp, "p"); + DUMP(p, in_nmi, "x"); DUMP(p, in_mce, "x"); DUMP(p, hmi_event_available, "x"); #endif