From patchwork Mon Jul 6 04:35:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhishek Goel X-Patchwork-Id: 1323331 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 (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B0Y7H12nxz9sSd for ; Mon, 6 Jul 2020 14:51:23 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.vnet.ibm.com Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4B0Y7D2Zr0zDqJL for ; Mon, 6 Jul 2020 14:51:20 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.158.5; helo=mx0b-001b2d01.pphosted.com; envelope-from=huntbag@linux.vnet.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=fail (p=none dis=none) header.from=linux.vnet.ibm.com Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4B0XqL5cblzDqgC for ; Mon, 6 Jul 2020 14:37:28 +1000 (AEST) Received: from pps.filterd (m0127361.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 0664X8gx149174; Mon, 6 Jul 2020 00:37:21 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3237cfn11j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 06 Jul 2020 00:37:21 -0400 Received: from m0127361.ppops.net (m0127361.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id 0664YmQD152545; Mon, 6 Jul 2020 00:37:20 -0400 Received: from ppma06fra.de.ibm.com (48.49.7a9f.ip4.static.sl-reverse.com [159.122.73.72]) by mx0a-001b2d01.pphosted.com with ESMTP id 3237cfn112-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 06 Jul 2020 00:37:20 -0400 Received: from pps.filterd (ppma06fra.de.ibm.com [127.0.0.1]) by ppma06fra.de.ibm.com (8.16.0.42/8.16.0.42) with SMTP id 0664LpeB023819; Mon, 6 Jul 2020 04:37:19 GMT Received: from b06cxnps4075.portsmouth.uk.ibm.com (d06relay12.portsmouth.uk.ibm.com [9.149.109.197]) by ppma06fra.de.ibm.com with ESMTP id 322h1g8x5a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 06 Jul 2020 04:37:18 +0000 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 0664bGIl852354 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 6 Jul 2020 04:37:16 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E7CD011C04A; Mon, 6 Jul 2020 04:37:15 +0000 (GMT) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8739111C050; Mon, 6 Jul 2020 04:37:14 +0000 (GMT) Received: from bostonp9.aus.stglabs.ibm.com (unknown [9.3.23.179]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTP; Mon, 6 Jul 2020 04:37:14 +0000 (GMT) From: Abhishek Goel To: skiboot@lists.ozlabs.org Date: Sun, 5 Jul 2020 23:35:33 -0500 Message-Id: <20200706043533.76539-1-huntbag@linux.vnet.ibm.com> X-Mailer: git-send-email 2.17.1 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235, 18.0.687 definitions=2020-07-06_02:2020-07-06, 2020-07-06 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=1 bulkscore=0 priorityscore=1501 phishscore=0 impostorscore=0 spamscore=0 adultscore=0 mlxlogscore=999 clxscore=1011 cotscore=-2147483648 malwarescore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2007060035 Subject: [Skiboot] [RFC v2 1/2] opal : Support for pre-entry and post-exit of stop state in opal 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: , Cc: ego@linux.vnet.ibm.com, mikey@neuling.org, psampat@linux.ibm.com MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch provides opal support for save restore of sprs in idle stop loop for LE opal. Opal support for stop states is needed to selectively enable stop states or to introduce a quirk quickly in case a buggy stop state is present. We make a opal call from kernel if firmware-stop-support for stop states is enabled. All the quirks for pre-entry of stop state is handled inside opal. A call from opal is made into kernel where we execute stop afer saving of NVGPRs. After waking up from 0x100 vector in kernel, we enter back into opal. All the quirks in post exit path, if any, are then handled in opal, from where we return successfully back to kernel. This patch provide support for shallow stop state only. Signed-off-by: Abhishek Goel Signed-off-by: Nicholas Piggin --- v1->v2 : Rebased the patch on Nick's Opal V4 branch core/opal.c | 90 +++++++++++++++++++++++++++++++++++++++++ include/opal-api.h | 5 ++- include/opal-internal.h | 2 + include/processor.h | 3 ++ 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/core/opal.c b/core/opal.c index bb71ac37..f4142b04 100644 --- a/core/opal.c +++ b/core/opal.c @@ -512,6 +512,9 @@ static int64_t opal_register_os_ops(struct opal_os_ops *ops, uint64_t size) vm_resurrect(); } + if (size >= 32) + os_ops.os_idle_stop = (void *) be64_to_cpu(ops->os_idle_stop); + checksum_romem(); opal_v4_os = true; @@ -556,6 +559,93 @@ void os_vm_unmap(uint64_t ea) mtmsrd(cpu->opal_call_msr, 0); } +struct p9_sprs { + /* per thread sprs that get lost in shallow states */ + u64 amr; + u64 iamr; + u64 amor; + u64 uamor; +}; + +/* + * Opal function to handle idle stop in kernel. + */ +static int64_t opal_cpu_idle(uint64_t srr1_addr, uint64_t psscr) +{ + int pvr; + u64 mmcra; + u64 mmcr0 = 0; + struct p9_sprs sprs = {}; + u64 *le_srr1 = (u64 *)be64_to_cpu(srr1_addr); + + if (!os_ops.os_idle_stop) + return OPAL_UNSUPPORTED; + + if (proc_gen != proc_gen_p9) + return OPAL_UNSUPPORTED; + + /* Deep states are not supported for opal fallback */ + if ((psscr & OPAL_PM_PSSCR_RL_MASK) >= 4) + return OPAL_UNSUPPORTED; + + pvr = mfspr(SPR_PVR); + if (!(psscr & (OPAL_PM_PSSCR_EC|OPAL_PM_PSSCR_ESL))) { + *le_srr1 = os_ops.os_idle_stop(srr1_addr, psscr); + goto out; + } + + /* EC=ESL=1 case */ + if (PVR_VERS_MAJ(pvr) == 2 && (PVR_VERS_MIN(pvr) == 0)) + /* + * POWER9 DD2 can incorrectly set PMAO when waking up + * after a state-loss idle. Saving and restoring MMCR0 + * over idle is a workaround. + */ + mmcr0 = mfspr(SPR_MMCR0); + + /* Save sprs lost in shallow state */ + sprs.amr = mfspr(SPR_AMR); + sprs.iamr = mfspr(SPR_IAMR); + sprs.amor = mfspr(SPR_AMOR); + sprs.uamor = mfspr(SPR_UAMOR); + + *le_srr1 = os_ops.os_idle_stop(srr1_addr, psscr); + + if ((*le_srr1 & SPR_SRR1_PM_WAKE_MASK) != SPR_SRR1_PM_WAKE_NOLOSS) { + + mtspr(SPR_AMR, sprs.amr); + mtspr(SPR_IAMR, sprs.iamr); + mtspr(SPR_AMOR, sprs.amor); + mtspr(SPR_UAMOR, sprs.uamor); + /* + * Workaround for POWER9 DD2.0, if we lost resources, the ERAT + * might have been corrupted and needs flushing. We also need + * to reload MMCR0 (see mmcr0 comment above). + */ + if (PVR_VERS_MAJ(pvr) == 2 && (PVR_VERS_MIN(pvr) == 0)) { + /* Handle PPC_ISA_3_0_INVALIDATE_ERAT */ + asm volatile (".long 0x7c1003e4" : : : "memory"); + mtspr(SPR_MMCR0, mmcr0); + } + + /* + * DD2.2 and earlier need to set then clear bit 60 in MMCRA + * to ensure the PMU starts running. + */ + if (PVR_VERS_MAJ(pvr) == 2 && (PVR_VERS_MIN(pvr) <= 2)) { + mmcra = mfspr(SPR_MMCRA); + mmcra |= PPC_BIT(60); + mtspr(SPR_MMCRA, mmcra); + mmcra &= ~PPC_BIT(60); + mtspr(SPR_MMCRA, mmcra); + } + } + +out: + return OPAL_SUCCESS; +} +opal_call(OPAL_CPU_IDLE, opal_cpu_idle, 2); + void add_opal_node(void) { uint64_t base, entry, size; diff --git a/include/opal-api.h b/include/opal-api.h index 3c630f02..08429d72 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -232,7 +232,8 @@ #define OPAL_REPORT_TRAP 183 #define OPAL_FIND_VM_AREA 184 #define OPAL_REGISTER_OS_OPS 185 -#define OPAL_LAST 185 +#define OPAL_CPU_IDLE 186 +#define OPAL_LAST 186 #define QUIESCE_HOLD 1 /* Spin all calls at entry */ #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */ @@ -1280,7 +1281,7 @@ struct opal_os_ops { __be64 os_printf; /* void printf(int32_t level, const char *str) */ __be64 os_vm_map; /* void os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags) */ __be64 os_vm_unmap; /* static void os_vm_unmap(uint64_t ea) */ - + __be64 os_idle_stop; /* void os_idle_stop(uint64_t srr1_addr, uint64_t psscr) */ }; #endif /* __ASSEMBLY__ */ diff --git a/include/opal-internal.h b/include/opal-internal.h index af521663..63f1c10c 100644 --- a/include/opal-internal.h +++ b/include/opal-internal.h @@ -22,6 +22,7 @@ struct os_ops { void (*os_printf)(uint32_t log_level, const char *str); int64_t (*os_vm_map)(uint64_t ea, uint64_t pa, uint64_t flags); void (*os_vm_unmap)(uint64_t ea); + int64_t (*os_idle_stop)(uint64_t srr1_addr, uint64_t psscr); }; extern bool opal_v4_os; @@ -30,6 +31,7 @@ extern struct os_ops os_ops; extern void os_printf(uint32_t log_level, const char *str); extern int64_t os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags); extern void os_vm_unmap(uint64_t ea); +extern int64_t os_idle_stop(uint64_t srr1_addr, uint64_t psscr); #ifdef __CHECKER__ #define __opal_func_test_arg(__func, __nargs) 0 diff --git a/include/processor.h b/include/processor.h index 9d197ffc..860f3fb3 100644 --- a/include/processor.h +++ b/include/processor.h @@ -77,12 +77,15 @@ #define SPR_HID4 0x3f4 #define SPR_HID5 0x3f6 #define SPR_PIR 0x3ff /* RO: Processor Identification */ +#define SPR_MMCR0 795 +#define SPR_MMCRA 0x312 /* Bits in SRR1 */ #define SPR_SRR1_PM_WAKE_MASK 0x3c0000 /* PM wake reason for P8/9 */ #define SPR_SRR1_PM_WAKE_SRESET 0x100000 #define SPR_SRR1_PM_WAKE_MCE 0x3c0000 /* Use reserved value for MCE */ +#define SPR_SRR1_PM_WAKE_NOLOSS 0x100000 /* Bits in DSISR */