From patchwork Thu Aug 8 15:13:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shiyang Ruan X-Patchwork-Id: 13757854 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2196C52D7B for ; Thu, 8 Aug 2024 15:13:43 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 493656B00EC; Thu, 8 Aug 2024 11:13:41 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 3F6636B00EE; Thu, 8 Aug 2024 11:13:41 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 15EE06B00ED; Thu, 8 Aug 2024 11:13:41 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id E1EA16B00EB for ; Thu, 8 Aug 2024 11:13:40 -0400 (EDT) Received: from smtpin13.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 6381281321 for ; Thu, 8 Aug 2024 15:13:40 +0000 (UTC) X-FDA: 82429422600.13.9EF29E7 Received: from esa10.hc1455-7.c3s2.iphmx.com (esa10.hc1455-7.c3s2.iphmx.com [139.138.36.225]) by imf09.hostedemail.com (Postfix) with ESMTP id D0637140017 for ; Thu, 8 Aug 2024 15:13:37 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=fujitsu.com header.s=fj2 header.b=MFAdByq1; spf=pass (imf09.hostedemail.com: domain of ruansy.fnst@fujitsu.com designates 139.138.36.225 as permitted sender) smtp.mailfrom=ruansy.fnst@fujitsu.com; dmarc=pass (policy=reject) header.from=fujitsu.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1723129931; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=v14/iHD72wpMklXcfm9tv3/7i6uAtVHzhlpwqpzLSD4=; b=et4pw9H/3p2ZiGhYYEeQVOej/Ne6JrMCIGKf+6VKMMcco0N6BHSqCYdQ1OzHLZ0t0SAvz0 Kzatm+htkFMgj9pZ0gdDCNzaAatx3NA24uKyg0m1KmvEiHQdAxbobpy+BqfegDcaKDiOur 7ItVSZc7M+WW8V4+/DNKcwRg3PglvQc= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=fujitsu.com header.s=fj2 header.b=MFAdByq1; spf=pass (imf09.hostedemail.com: domain of ruansy.fnst@fujitsu.com designates 139.138.36.225 as permitted sender) smtp.mailfrom=ruansy.fnst@fujitsu.com; dmarc=pass (policy=reject) header.from=fujitsu.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1723129931; a=rsa-sha256; cv=none; b=wL8LznsD3VUT/owZ/x+jLl7TfXaN9cR7t60iG6i5hgPSl8ipKD8ad2pLA7V5LVbQRp9oCF CIzd1IfnMXAp0jBE95pn86dMleKzoA0EcQa9e3FLDGvfRRi3LzehXN7GIMrsCLNzpq+YN7 +Kh/gCbUTwZZYSXNLIvU8VzTjY805jE= DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=fujitsu.com; i=@fujitsu.com; q=dns/txt; s=fj2; t=1723130017; x=1754666017; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=V+txiutig01/lSTX5GU2xXQ/Ecok4xMPvtbSdLTFmbo=; b=MFAdByq1WsLEYk0IQWd1pC5ab3SF6zGCCi6M2aftghyMBfgo4GNdMyJN eWkl1cJuHRYhOQkEyFdJQC3n6VjjF2d/CTNK/fycVIOpe1H9ueotjL1xi YP6a+XulnGghUD+2x1E7K+BTuDxWhGGMXa6GG6TQMWUJ2t3VuFGCAH7da GaFvZwOEJQwLL3k22RucXoQLs5pm+YMC6AgGM53j9RSlUNGUY5tDfj2Sk EI3aB9JPwBDHl4mnK8JTdi52eNHQcnEWYQsBof5S4pg+Z7ukwxcvcHX06 0hNwZsHqJCnB5xn0n04UJ/AF+Ci0gGHGMcClzeYdbaZHWTKe1jebCDAW5 w==; X-CSE-ConnectionGUID: HJ5MG+D3QXOlZ4wfsmmgqg== X-CSE-MsgGUID: HhW2HzuST0OSp8FBAU8CpA== X-IronPort-AV: E=McAfee;i="6700,10204,11158"; a="157585582" X-IronPort-AV: E=Sophos;i="6.09,273,1716217200"; d="scan'208";a="157585582" Received: from unknown (HELO yto-r2.gw.nic.fujitsu.com) ([218.44.52.218]) by esa10.hc1455-7.c3s2.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Aug 2024 00:13:35 +0900 Received: from yto-m2.gw.nic.fujitsu.com (yto-nat-yto-m2.gw.nic.fujitsu.com [192.168.83.65]) by yto-r2.gw.nic.fujitsu.com (Postfix) with ESMTP id 8327BC68E1 for ; Fri, 9 Aug 2024 00:13:33 +0900 (JST) Received: from kws-ab4.gw.nic.fujitsu.com (kws-ab4.gw.nic.fujitsu.com [192.51.206.22]) by yto-m2.gw.nic.fujitsu.com (Postfix) with ESMTP id BA9CFD5115 for ; Fri, 9 Aug 2024 00:13:32 +0900 (JST) Received: from edo.cn.fujitsu.com (edo.cn.fujitsu.com [10.167.33.5]) by kws-ab4.gw.nic.fujitsu.com (Postfix) with ESMTP id 2C7DA229360 for ; Fri, 9 Aug 2024 00:13:32 +0900 (JST) Received: from irides.g08.fujitsu.local (unknown [10.167.226.114]) by edo.cn.fujitsu.com (Postfix) with ESMTP id 4D8B81A000A; Thu, 8 Aug 2024 23:13:31 +0800 (CST) From: Shiyang Ruan To: qemu-devel@nongnu.org, linux-cxl@vger.kernel.org, linux-edac@vger.kernel.org, linux-mm@kvack.org, dan.j.williams@intel.com, vishal.l.verma@intel.com, Jonathan.Cameron@huawei.com, alison.schofield@intel.com Cc: bp@alien8.de, dave.jiang@intel.com, dave@stgolabs.net, ira.weiny@intel.com, james.morse@arm.com, linmiaohe@huawei.com, mchehab@kernel.org, nao.horiguchi@gmail.com, rric@kernel.org, tony.luck@intel.com, ruansy.fnst@fujitsu.com Subject: [PATCH v4 2/2] cxl: avoid duplicated report from MCE & device Date: Thu, 8 Aug 2024 23:13:28 +0800 Message-Id: <20240808151328.707869-3-ruansy.fnst@fujitsu.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240808151328.707869-1-ruansy.fnst@fujitsu.com> References: <20240808151328.707869-1-ruansy.fnst@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-TM-AS-Product-Ver: IMSS-9.1.0.1417-9.0.0.1002-28584.000 X-TM-AS-User-Approved-Sender: Yes X-TMASE-Version: IMSS-9.1.0.1417-9.0.1002-28584.000 X-TMASE-Result: 10--16.139300-10.000000 X-TMASE-MatchedRID: mBR/8PU27l8ZHQl0dvECsazGfgakLdjaKQNhMboqZlpqrsOvUFEKy3kY O/9k4Xg2bn+bq+W8j6XQJxNDXN5QxO4rOj+PdZuMVnzlQiaE21qxXA8wqNmbVrwYtb0g7Ywtu0m nSBAOWht+3E64qYVhyfoS5B31PW6f3tF9vYxzQ43wgrvJFY9E0Vvh1cEykiSGLX3qyf3ewG+qbv 7m/AcFJSbOYzaQt2Phra3G1NjT5m2njNSDi/vkV02xVQmDwU6mCZa9cSpBObnAuQ0xDMaXkH4qt YI9sRE/4K9FmervsqWylFSPywhifTBF72xzhJLNyRfzRkrgkUHzWEMQjooUzbs3Yh2IOCYz/svd Vly7w9ldRSgb+5TWboftADTYJ316uybvDkIalGDHyCtnYFmFhoIw3bnTjwR6icvz9DxarMGk86u MB98iNvBn25uFP/vzYcMGA+vBhspccQ8eam5EfRRFJJyf5BJe3QfwsVk0UbslCGssfkpInQ== X-TMASE-SNAP-Result: 1.821001.0001-0-1-22:0,33:0,34:0-0 X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: D0637140017 X-Stat-Signature: 6fr9f7wo19qd5qw5hrs3nyw9885impj8 X-Rspam-User: X-HE-Tag: 1723130017-831026 X-HE-Meta: U2FsdGVkX1+sAc6nOq2QcpMcURycUcuEsLqtYUhzeE/LN3Ue5NIeGg2DHOk9AtlP0vwKOvVwjAG+cm0gXs9Z7xWsrUGTG2l7b/yqM3KUxi+BLP9+05sM8CjYAiUnrR4aLUFrVU2Dhm8WsDBNkPp6oKROVH85zgIX8LklqFVEIWIeUdqLWqiWanKU0Ei5Qb2bDVJznRuLagZW4jW8QloD51W4+ka6fn08+HyZ1rsJxnepAUldx9Eggh38vzBWnhs1g9cX57qF5DM1Vl9W3MKqdOzseVk6rIiPzvskyAOMfqeOrlOvLFf+zFuAYXBx6XqFTrqc6g590TpnpNCd3bVzEO36Wo7ghNeaRT+vTPr/R2BRQBXvdzui5+Gwzty/mNmI6ENWbZqcRnFiF2E+BDw0amCIpu0RKZ7C8Hpv5DShGL1bdERbVp0HraWRirZNKtF+ormuTrAg3OTGCIjpl3zn6foOQvpVNCNWIEVFlV0qThb2XInVuKIHfOZu4bzJ4efMG+S/6CEB0uEzLT1AKbvLttqSZvwJJ3n9gdUyufSWmY2EAvGoHEQiTud183jWf0zz2WiiClKkWZa0/isM2QQa/egse9bhYbkVPcrSbXTazRXmfa4qiLxh1RZxgfuAgfSdr8Kxrc5UCxAy/SCVAT9byA9qJOcdqN5U7BH2sCshHpdb7l3RqSi20xefh/ZubtzrIvHUM7RaqKPC5jz6PhI/FG6g8dapVzuCy6NRJEoOdsgwsd9s8Q068a+edGRcV+Fi+CHnYmMU06l67DedAo172J10tgOB9jyD40BxUfvTZ7KYJpa+v78JWqH3NDsllb+yzitUZZk2U0RtPC8x6JRJXpmNK4dL2epcpT4Q/qUQOHkyWHEhQVNiqPkQB+mNPgC0r4Z0WdkwGr4aG6NlRPzbyoupXqjrJ4GB3YZoWXmCPQge4QgZz/3sAEJb2LCdi93O0XmEkEMOY6NA5qpzqOJ dweBZmlU wokrUfURFGQZBJz/qeVyYP/tBOsbucQr3y5cvgM76NV0NJbxqYmZPATRjke0aV/NTsPL4NxZFZSznLp7o8FNNXV5oqPH3gXvqdyTRPxg4++Rixh0IyoRuKlqzuKkvpWi3xf2Yu6nm490Y24PCFoIP1/nz10O/ExlgJikE/Yd0D7jWCfYflGf9T7KyivukhgiBSK9f/zZ9ynz5YChWFTg1v9deSbJ3Jo9JdLj4mx2EqL2gvlj+ttrn9B21+45CbsUvM+vKh9xMuqxE1gXrxc6W6WJ+v/uOkuTqjKkpFUJVdOlj0tF8IQvZmL8Xbg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Since CXL device is a memory device, while CPU is consuming a poison page of CXL device, it always triggers a MCE (via interrupt #18) and calls memory_failure() to handle POISON page, no matter which-First path is configured. CXL device could also find and report the POISON, kernel now not only traces but also calls memory_failure() to handle it, which is marked as "NEW" in the figure blow. ``` 1. MCE (interrupt #18, while CPU consuming POISON) -> do_machine_check() -> mce_log() -> notify chain (x86_mce_decoder_chain) -> memory_failure() <---------------------------- EXISTS 2.a FW-First (optional, CXL device proactively find&report) -> CXL device -> Firmware -> OS: ACPI->APEI->GHES->CPER -> CXL driver -> trace \-> memory_failure() ^----- NEW 2.b OS-First (optional, CXL device proactively find&report) -> CXL device -> MSI -> OS: CXL driver -> trace \-> memory_failure() ^------------------------------- NEW ``` But in this way, the memory_failure() could be called twice or even at same time, as is shown in the figure above: (1.) and (2.a or 2.b), before the POISON page is cleared. memory_failure() has it own mutex lock so it actually won't be called at same time and the later call could be avoided because HWPoison bit has been set. However, assume such a scenario, "CXL device reports POISON error" triggers 1st call, user see it from log and want to clear the poison by executing `cxl clear-poison` command, and at the same time, a process tries to access this POISON page, which triggers MCE (it's the 2nd call). Since there is no lock between the 2nd call with clearing poison operation, race condition may happen, which may cause HWPoison bit of the page in an unknown state. Thus, we have to avoid the 2nd call. This patch[2] introduces a new notifier_block into `x86_mce_decoder_chain` and a POISON cache list, to stop the 2nd call of memory_failure(). It checks whether the current poison page has been reported (if yes, stop the notifier chain, don't call the following memory_failure() to report again). Signed-off-by: Shiyang Ruan --- arch/x86/include/asm/mce.h | 1 + drivers/cxl/core/mbox.c | 115 +++++++++++++++++++++++++++++++++++++ drivers/cxl/core/memdev.c | 6 +- drivers/cxl/cxlmem.h | 3 + 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 3ad29b128943..5da45e870858 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -182,6 +182,7 @@ enum mce_notifier_prios { MCE_PRIO_NFIT, MCE_PRIO_EXTLOG, MCE_PRIO_UC, + MCE_PRIO_CXL, MCE_PRIO_EARLY, MCE_PRIO_CEC, MCE_PRIO_HIGHEST = MCE_PRIO_CEC diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 0cb6ef2e6600..b21700428c35 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -925,6 +927,9 @@ void cxl_event_handle_record(struct cxl_memdev *cxlmd, if (cxlr) hpa = cxl_dpa_to_hpa(cxlr, cxlmd, dpa); + if (hpa != ULLONG_MAX && cxl_mce_recorded(hpa)) + return; + if (event_type == CXL_CPER_EVENT_GEN_MEDIA) { trace_cxl_general_media(cxlmd, type, cxlr, hpa, &evt->gen_media); @@ -1457,6 +1462,112 @@ int cxl_poison_state_init(struct cxl_memdev_state *mds) } EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL); +DEFINE_XARRAY(cxl_mce_records); + +bool cxl_mce_recorded(u64 hpa) +{ + XA_STATE(xas, &cxl_mce_records, hpa); + void *entry; + + xas_lock_irq(&xas); + entry = xas_load(&xas); + if (entry) { + xas_unlock_irq(&xas); + return true; + } + entry = xa_mk_value(hpa); + xas_store(&xas, entry); + xas_unlock_irq(&xas); + + return false; +} +EXPORT_SYMBOL_NS_GPL(cxl_mce_recorded, CXL); + +void cxl_mce_clear(u64 hpa) +{ + XA_STATE(xas, &cxl_mce_records, hpa); + void *entry; + + xas_lock_irq(&xas); + entry = xas_load(&xas); + if (entry) { + xas_store(&xas, NULL); + } + xas_unlock_irq(&xas); +} +EXPORT_SYMBOL_NS_GPL(cxl_mce_clear, CXL); + +struct cxl_contains_hpa_context { + bool contains; + u64 hpa; +}; + +static int __cxl_contains_hpa(struct device *dev, void *arg) +{ + struct cxl_contains_hpa_context *ctx = arg; + struct cxl_endpoint_decoder *cxled; + struct range *range; + u64 hpa = ctx->hpa; + + if (!is_endpoint_decoder(dev)) + return 0; + + cxled = to_cxl_endpoint_decoder(dev); + range = &cxled->cxld.hpa_range; + + if (range->start <= hpa && hpa <= range->end) { + ctx->contains = true; + return 1; + } + + return 0; +} + +static bool cxl_contains_hpa(const struct cxl_memdev *cxlmd, u64 hpa) +{ + struct cxl_contains_hpa_context ctx = { + .contains = false, + .hpa = hpa, + }; + struct cxl_port *port; + + port = cxlmd->endpoint; + guard(rwsem_write)(&cxl_region_rwsem); + if (port && cxl_num_decoders_committed(port)) + device_for_each_child(&port->dev, &ctx, __cxl_contains_hpa); + + return ctx.contains; +} + +static int cxl_handle_mce(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct mce *mce = (struct mce *)data; + struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state, + mce_notifier); + u64 hpa; + + if (!mce || !mce_usable_address(mce)) + return NOTIFY_DONE; + + hpa = mce->addr & MCI_ADDR_PHYSADDR; + + /* Check if the PFN is located on this CXL device */ + if (!pfn_valid(hpa >> PAGE_SHIFT) && + !cxl_contains_hpa(mds->cxlds.cxlmd, hpa)) + return NOTIFY_DONE; + + /* + * Search PFN in the cxl_mce_records, if already exists, don't continue + * to do memory_failure() to avoid a poison address being reported + * more than once. + */ + if (cxl_mce_recorded(hpa)) + return NOTIFY_STOP; + else + return NOTIFY_OK; +} + struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) { struct cxl_memdev_state *mds; @@ -1476,6 +1587,10 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) mds->ram_perf.qos_class = CXL_QOS_CLASS_INVALID; mds->pmem_perf.qos_class = CXL_QOS_CLASS_INVALID; + mds->mce_notifier.notifier_call = cxl_handle_mce; + mds->mce_notifier.priority = MCE_PRIO_CXL; + mce_register_decode_chain(&mds->mce_notifier); + return mds; } EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, CXL); diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 0277726afd04..9d4ed4dc4d51 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -376,10 +376,14 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) goto out; cxlr = cxl_dpa_to_region(cxlmd, dpa); - if (cxlr) + if (cxlr) { + u64 hpa = cxl_dpa_to_hpa(cxlr, cxlmd, dpa); + + cxl_mce_clear(hpa); dev_warn_once(mds->cxlds.dev, "poison clear dpa:%#llx region: %s\n", dpa, dev_name(&cxlr->dev)); + } record = (struct cxl_poison_record) { .address = cpu_to_le64(dpa), diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 5c4810dcbdeb..d2d906c26755 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -502,6 +502,7 @@ struct cxl_memdev_state { struct cxl_fw_state fw; struct rcuwait mbox_wait; + struct notifier_block mce_notifier; int (*mbox_send)(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd); }; @@ -837,6 +838,8 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, int cxl_trigger_poison_list(struct cxl_memdev *cxlmd); int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa); int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa); +bool cxl_mce_recorded(u64 pfn); +void cxl_mce_clear(u64 pfn); #ifdef CONFIG_CXL_SUSPEND void cxl_mem_active_inc(void);