From patchwork Thu Apr 5 07:15:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Balbir Singh X-Patchwork-Id: 895294 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40GvTr6p8Sz9s0y for ; Thu, 5 Apr 2018 17:24:32 +1000 (AEST) 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="BA3+J1fv"; 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 40GvTr5L9SzF1qv for ; Thu, 5 Apr 2018 17:24:32 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="BA3+J1fv"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4001:c06::243; helo=mail-io0-x243.google.com; envelope-from=bsingharora@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="BA3+J1fv"; dkim-atps=neutral Received: from mail-io0-x243.google.com (mail-io0-x243.google.com [IPv6:2607:f8b0:4001:c06::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 40GvHF6NMbzF1sR for ; Thu, 5 Apr 2018 17:15:21 +1000 (AEST) Received: by mail-io0-x243.google.com with SMTP id e79so29380748ioi.7 for ; Thu, 05 Apr 2018 00:15:21 -0700 (PDT) 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=NYlyOx8AW5CAZXv8/Z6NfSz4bpQYIAuS3+WBhKiLXH4=; b=BA3+J1fveIxrQH9sy+Qzcn/FdHTtIcpHcRaRJ4MWx6riC6P4h/LOPLZ6ILUZcaQzTU Fdsj6Sg0nnX6LHu2YX3AicfZPQ6wEbp538lbSUkBQxnmxYZeDw8uoPzoUjWmj4dv+EJo jgNoQa/6LqIFbKywWcUZTCwmdw6HkJx0fwmEMcRCiCG7LZnO3L+RB4LSMHhXd8QBAhDD /jJPWbQ27sk7843W9d9v2spE1j9lj8RWG9IS4Ry11lUESWrfoPjqm9rLW+IHNH5fAlG4 T2EnrHgQPeE+H27YdqbeuoYmI4/HpNH55hecST/NBTzodN93uQltBJzIEvuI88FxKVzU tvYg== 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=NYlyOx8AW5CAZXv8/Z6NfSz4bpQYIAuS3+WBhKiLXH4=; b=fZA+zUPSZJ3KJ5/eJKnp3BOk5wYmRYMyxpE9jINN42+uZ702iz4c+qpsiV0PvpuuU5 oqLj7vQASJYM01zRxaX+vca4t1GK1Dp5XG5tW2Q6hiOrWkujlJFi4DeBQF0Jkc04twcm Bz7pKG310oBNQOWLgcfLIvQ53qFbRuKIhp9MWGBzwkr5rkVuODaKnTm6yEtfvYrJmYYS 8+XbCqqP4e3F0QkGNGZ/CNhOQeJWExhRk98bbWG0V4DcOrQCPuOWlcWsH166xo3jRZEx ifRWkcHE1+48dHAkwIDKO/zy1bVrgflAwICDQLu9aP+wFJxeCT8oyijTcnyHipryI9Pn Bm+g== X-Gm-Message-State: ALQs6tAyu4ouwMvi/mvoMMeQSD7+9NXPPzUeAwlMVejVo03KBu5rACb3 XI2eHFDwppervpxx48VdK8pTawoH X-Google-Smtp-Source: AIpwx48k13MSFo7tZDO74DhkLx5YxAp0sZQFMYaNqgKopLnIbbvMh/zZqHdkb6/45IlkQAd7WZ9VBA== X-Received: by 10.107.11.91 with SMTP id v88mr20572581ioi.28.1522912519830; Thu, 05 Apr 2018 00:15:19 -0700 (PDT) Received: from balbir.ozlabs.ibm.com ([122.99.82.10]) by smtp.googlemail.com with ESMTPSA id n22sm435973iob.33.2018.04.05.00.15.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 05 Apr 2018 00:15:19 -0700 (PDT) From: Balbir Singh To: linuxppc-dev@lists.ozlabs.org Subject: [PATCH v2 3/3] powerpc/mce: Handle memcpy_mcsafe Date: Thu, 5 Apr 2018 17:15:00 +1000 Message-Id: <20180405071500.22320-4-bsingharora@gmail.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180405071500.22320-1-bsingharora@gmail.com> References: <20180405071500.22320-1-bsingharora@gmail.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: oohall@gmail.com, npiggin@gmail.com, linux-nvdimm@lists.01.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Add a blocking notifier callback to be called in real-mode on machine check exceptions for UE (ld/st) errors only. The patch registers a callback on boot to be notified of machine check exceptions and returns a NOTIFY_STOP when a page of interest is seen as the source of the machine check exception. This page of interest is a ZONE_DEVICE page and hence for now, for memcpy_mcsafe to work, the page needs to belong to ZONE_DEVICE and memcpy_mcsafe should be used to access the memory. The patch also modifies the NIP of the exception context to go back to the fixup handler (in memcpy_mcsafe) and does not print any error message as the error is treated as returned via a return value and handled. Signed-off-by: Balbir Singh --- arch/powerpc/include/asm/mce.h | 3 +- arch/powerpc/kernel/mce.c | 77 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index 3a1226e9b465..a76638e3e47e 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -125,7 +125,8 @@ struct machine_check_event { enum MCE_UeErrorType ue_error_type:8; uint8_t effective_address_provided; uint8_t physical_address_provided; - uint8_t reserved_1[5]; + uint8_t error_return; + uint8_t reserved_1[4]; uint64_t effective_address; uint64_t physical_address; uint8_t reserved_2[8]; diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index efdd16a79075..b9e4881fa8c5 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -28,7 +28,9 @@ #include #include #include +#include +#include #include #include @@ -54,6 +56,52 @@ static struct irq_work mce_event_process_work = { DECLARE_WORK(mce_ue_event_work, machine_process_ue_event); +static BLOCKING_NOTIFIER_HEAD(mce_notifier_list); + +int register_mce_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&mce_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(register_mce_notifier); + +int unregister_mce_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&mce_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(unregister_mce_notifier); + + +static int check_memcpy_mcsafe(struct notifier_block *nb, + unsigned long val, void *data) +{ + /* + * val contains the physical_address of the bad address + */ + unsigned long pfn = val >> PAGE_SHIFT; + struct page *page = realmode_pfn_to_page(pfn); + int rc = NOTIFY_DONE; + + if (!page) + goto out; + + if (is_zone_device_page(page)) /* for HMM and PMEM */ + rc = NOTIFY_STOP; +out: + return rc; +} + +struct notifier_block memcpy_mcsafe_nb = { + .priority = 0, + .notifier_call = check_memcpy_mcsafe, +}; + +int mce_mcsafe_register(void) +{ + register_mce_notifier(&memcpy_mcsafe_nb); + return 0; +} +arch_initcall(mce_mcsafe_register); + static void mce_set_error_info(struct machine_check_event *mce, struct mce_error_info *mce_err) { @@ -151,9 +199,31 @@ void save_mce_event(struct pt_regs *regs, long handled, mce->u.ue_error.effective_address_provided = true; mce->u.ue_error.effective_address = addr; if (phys_addr != ULONG_MAX) { + int rc; + const struct exception_table_entry *entry; + + /* + * Once we have the physical address, we check to + * see if the current nip has a fixup entry. + * Having a fixup entry plus the notifier stating + * that it can handle the exception is an indication + * that we should return to the fixup entry and + * return an error from there + */ mce->u.ue_error.physical_address_provided = true; mce->u.ue_error.physical_address = phys_addr; - machine_check_ue_event(mce); + + rc = blocking_notifier_call_chain(&mce_notifier_list, + phys_addr, NULL); + if (rc & NOTIFY_STOP_MASK) { + entry = search_exception_tables(regs->nip); + if (entry != NULL) { + mce->u.ue_error.error_return = 1; + regs->nip = extable_fixup(entry); + } else + machine_check_ue_event(mce); + } else + machine_check_ue_event(mce); } } return; @@ -208,7 +278,6 @@ void release_mce_event(void) get_mce_event(NULL, true); } - /* * Queue up the MCE event which then can be handled later. */ @@ -239,6 +308,10 @@ void machine_check_queue_event(void) if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) return; + if (evt.error_type == MCE_ERROR_TYPE_UE && + evt.u.ue_error.error_return == 1) + return; + index = __this_cpu_inc_return(mce_queue_count) - 1; /* If queue is full, just return for now. */ if (index >= MAX_MC_EVT) {