From patchwork Mon Jan 7 14:04:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 1021353 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43YHN174q0z9sBn for ; Tue, 8 Jan 2019 01:10:09 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hQiFQEIv"; 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 43YHN15dfYzDqHZ for ; Tue, 8 Jan 2019 01:10:09 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::544; helo=mail-pg1-x544.google.com; envelope-from=npiggin@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hQiFQEIv"; dkim-atps=neutral Received: from mail-pg1-x544.google.com (mail-pg1-x544.google.com [IPv6:2607:f8b0:4864:20::544]) (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 43YHGP5gF6zDqDl for ; Tue, 8 Jan 2019 01:05:17 +1100 (AEDT) Received: by mail-pg1-x544.google.com with SMTP id g189so189743pgc.5 for ; Mon, 07 Jan 2019 06:05:17 -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=GnJrqU9qY62hcf+FNxNghJHhTipLxZxuKsktkMGeJCU=; b=hQiFQEIvuAorG7zpVcxRWCUNxy6b4gtIs2HCkmXA0IGRUQiLoQ+uUHu5VmwclCD5PK WCuMsi7gC+YsZa7Nh5r8dFgYjFMbITVBP6xfzeQdqeSJdBQPyUYntBRA5AcnhCAa2jFs gxYNGBc0k22goHAz82YhX1FFC0lBDY0IQXaDvflUlHDgZ2p8+hEdGz77Dcb6s13MEehy 6P/K/4hMWvQq4NWvpS7HOyjjUzpZaaGG7c65JLiEfM7L7iLFrpPfHDJz787qZu09SiMt FhJblogQRCTAyefc+sqtu7uZf12A7Tkq7oX1utc4qBtYbn/w+SoNoHPvjxjDoTQYa/Xe qZvA== 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=GnJrqU9qY62hcf+FNxNghJHhTipLxZxuKsktkMGeJCU=; b=TQSTuwJuHijEXTzvGAtXW+Bj91Q4P025nhY/O3pH9U/EEeRpm45bjYKBX4i1ZfNa1a Ad3NoDN0wEbESYUEZsQu9vuo75gPQsQM1u7d/8wFtFeebfq63OY02S9X5I7dRl4kh2Nc trk4g901Hm9D2VEkEWCwYM14UHf8WXU7AhHdRukF8z/AhFqh20slpP/tLuAj1VrxNVXJ V9uS1oAAVdU1bFZjoIjXNRHGgf0UweCrIWX/lvlcsQFM1hnepSYcc9ilNJjeCvMzzf7C k0+tzMFrWX9JaDQQyM7mDbnd0Gezsp9z8ptBCrYz+vH0wUOWddnyk52cxhrB5NHmDyRh 7/yw== X-Gm-Message-State: AJcUukdGRCrA2QMd91D8R38i55RqQ3yqXv58bqHtHlsefDVIX1kR3jqd +dttwNdxz3MEog8IW37YFTPzx6vpRN8= X-Google-Smtp-Source: ALg8bN6SHP/mwPyQAp2mQTAyPmuWW7l7XWgejievvIx+Pj1OTKZ8fy7EurcP5riW8pMrHvyKanxutA== X-Received: by 2002:a63:4819:: with SMTP id v25mr10974653pga.308.1546869915823; Mon, 07 Jan 2019 06:05:15 -0800 (PST) Received: from roar.local0.net (193-116-118-220.tpgi.com.au. [193.116.118.220]) by smtp.gmail.com with ESMTPSA id z62sm114758918pfl.33.2019.01.07.06.05.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Jan 2019 06:05:15 -0800 (PST) From: Nicholas Piggin To: skiboot@lists.ozlabs.org Date: Tue, 8 Jan 2019 00:04:26 +1000 Message-Id: <20190107140428.16388-15-npiggin@gmail.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190107140428.16388-1-npiggin@gmail.com> References: <20190107140428.16388-1-npiggin@gmail.com> Subject: [Skiboot] [PATCH 14/16] core/exceptions: implement an exception handler for non-powersave sresets X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Detect non-powersave sresets and send them to the normal exception handler which prints registers and stack. Signed-off-by: Nicholas Piggin --- asm/head.S | 20 +++++++++++++++++++- core/cpu.c | 35 +++++++++++++++++++++++++++++------ core/exceptions.c | 24 ++++++++++++++++++++---- include/processor.h | 4 ++++ include/skiboot.h | 5 +++++ 5 files changed, 77 insertions(+), 11 deletions(-) diff --git a/asm/head.S b/asm/head.S index 0f2eccc39..85ca57cb7 100644 --- a/asm/head.S +++ b/asm/head.S @@ -107,6 +107,7 @@ hir_trigger: * used for recovering from rvw or nap mode */ . = 0x100 +sreset_vector: /* BML entry, load up r3 with device tree location */ li %r3, 0 oris %r3, %r3, 0xa @@ -666,8 +667,25 @@ enter_p9_pm_state: */ .global reset_patch_start reset_patch_start: + mtsprg0 %r3 + mtsprg1 %r4 + mfspr %r3,SPR_SRR1 + mfcr %r4 + rldicl. %r3,%r3,48,62 + bne 1f /* powersave wakeup (CFAR not required) */ + mtcr %r4 + mfspr %r3,SPR_CFAR + li %r4,0x100 + b _exception + (reset_patch_start - sreset_vector) +1: LOAD_IMM64(%r30, SKIBOOT_BASE) + cmpdi %r3,0x1 + bne 2f /* state loss */ + LOAD_IMM32(%r3, reset_resume - __head) + b 3f +2: LOAD_IMM32(%r3, reset_wakeup - __head) +3: add %r3,%r30,%r3 mtctr %r3 bctr @@ -713,7 +731,7 @@ reset_wakeup: REST_GPR(29,%r1) REST_GPR(30,%r1) REST_GPR(31,%r1) - +reset_resume: /* Get LR back, pop stack and return */ addi %r1,%r1,STACK_FRAMESIZE ld %r0,16(%r1) diff --git a/core/cpu.c b/core/cpu.c index e7ffe3003..4820beb31 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -380,14 +380,15 @@ enum cpu_wake_cause { cpu_wake_on_dec, }; -static void cpu_idle_p8(enum cpu_wake_cause wake_on) +static unsigned int cpu_idle_p8(enum cpu_wake_cause wake_on) { uint64_t lpcr = mfspr(SPR_LPCR) & ~SPR_LPCR_P8_PECE; struct cpu_thread *cpu = this_cpu(); + unsigned int vec = 0; if (!pm_enabled) { prlog_once(PR_DEBUG, "cpu_idle_p8 called pm disabled\n"); - return; + return vec; } /* Clean up ICP, be ready for IPIs */ @@ -426,6 +427,7 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on) /* Enter nap */ enter_p8_pm_state(false); + vec = 0x100; skip_sleep: /* Restore */ @@ -433,17 +435,20 @@ skip_sleep: cpu->in_idle = false; cpu->in_sleep = false; reset_cpu_icp(); + + return vec; } -static void cpu_idle_p9(enum cpu_wake_cause wake_on) +static unsigned int cpu_idle_p9(enum cpu_wake_cause wake_on) { uint64_t lpcr = mfspr(SPR_LPCR) & ~SPR_LPCR_P9_PECE; uint64_t psscr; struct cpu_thread *cpu = this_cpu(); + unsigned int vec = 0; if (!pm_enabled) { prlog_once(PR_DEBUG, "cpu_idle_p9 called pm disabled\n"); - return; + return vec; } /* Synchronize with wakers */ @@ -482,6 +487,7 @@ static void cpu_idle_p9(enum cpu_wake_cause wake_on) psscr = PPC_BIT(42) | PPC_BIT(43) | PPC_BITMASK(54, 55) | PPC_BIT(63); enter_p9_pm_state(psscr); + vec = 0x100; } else { /* stop with EC=0 (resumes) which does not require sreset. */ /* PSSCR SD=0 ESL=0 EC=0 PSSL=0 TR=3 MTL=0 RL=1 */ @@ -497,21 +503,38 @@ static void cpu_idle_p9(enum cpu_wake_cause wake_on) sync(); cpu->in_idle = false; cpu->in_sleep = false; + + return vec; } static void cpu_idle_pm(enum cpu_wake_cause wake_on) { + unsigned int vec; + switch(proc_gen) { case proc_gen_p8: - cpu_idle_p8(wake_on); + vec = cpu_idle_p8(wake_on); break; case proc_gen_p9: - cpu_idle_p9(wake_on); + vec = cpu_idle_p9(wake_on); break; default: + vec = 0; prlog_once(PR_DEBUG, "cpu_idle_pm called with bad processor type\n"); break; } + + if (vec == 0x100) { + unsigned long srr1 = mfspr(SPR_SRR1); + + switch (srr1 & SPR_SRR1_PM_WAKE_MASK) { + case SPR_SRR1_PM_WAKE_SRESET: + exception_entry_pm_sreset(); + break; + default: + break; + } + } } void cpu_idle_job(void) diff --git a/core/exceptions.c b/core/exceptions.c index f05bcfb9e..1c2917357 100644 --- a/core/exceptions.c +++ b/core/exceptions.c @@ -39,9 +39,6 @@ static void dump_regs(struct stack_frame *stack) i, stack->gpr[i], i + 16, stack->gpr[i + 16]); } -/* Called from head.S, thus no prototype */ -void __noreturn exception_entry(struct stack_frame *stack); - void __noreturn exception_entry(struct stack_frame *stack) { uint64_t nip; @@ -71,7 +68,10 @@ void __noreturn exception_entry(struct stack_frame *stack) prerror("***********************************************\n"); l = 0; - if (stack->type == 0x200) { + if (stack->type == 0x100) { + l += snprintf(buf + l, max - l, + "Fatal System Reset at "REG" ", nip); + } else if (stack->type == 0x200) { l += snprintf(buf + l, max - l, "Fatal MCE at "REG" ", nip); } else { @@ -86,6 +86,22 @@ void __noreturn exception_entry(struct stack_frame *stack) abort(); } +void __noreturn exception_entry_pm_sreset(void) +{ + const size_t max = 320; + char buf[max]; + size_t l; + + prerror("***********************************************\n"); + l = 0; + l += snprintf(buf + l, max - l, + "Fatal System Reset in sleep"); + prerror("%s\n", buf); + + abort(); +} + + static int64_t opal_register_exc_handler(uint64_t opal_exception __unused, uint64_t handler_address __unused, uint64_t glue_cache_line __unused) diff --git a/include/processor.h b/include/processor.h index 6b262b45e..70991dfb0 100644 --- a/include/processor.h +++ b/include/processor.h @@ -88,6 +88,10 @@ #define SPR_HID5 0x3f6 #define SPR_PIR 0x3ff /* RO: Processor Identification */ +/* Bits in SRR1 */ + +#define SPR_SRR1_PM_WAKE_MASK 0x3c0000 /* PM wake reason for P8/9 */ +#define SPR_SRR1_PM_WAKE_SRESET 0x100000 /* Bits in LPCR */ diff --git a/include/skiboot.h b/include/skiboot.h index 96caa2714..0f6a85520 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -285,6 +285,11 @@ extern void fast_sleep_exit(void); /* Fallback fake RTC */ extern void fake_rtc_init(void); +/* Exceptions */ +struct stack_frame; +extern void __noreturn exception_entry(struct stack_frame *stack); +extern void __noreturn exception_entry_pm_sreset(void); + /* Assembly in head.S */ extern void disable_machine_check(void); extern void enable_machine_check(void);