From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902736; cv=none; d=zohomail.com; s=zohoarc; b=FKzLeWfW3D+IirMjOaUCLeXTrO0xABXqJ237sYp1IEhBFJfpW4PiHyihbMyP8gsOwXqENwnv2HCRf2fpmC8BAShD3ThRQQ9hoJgIrH5vU+zoIkeJFZ/+Deh5lwXDmxGdDhYKkkGi4kzym8FSANPNJzFO0+bG+MHHMaiyJPhfF3A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902736; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=VRCn8+v5LD6aP2bcIhJkKzPTKJzDcJmvG9vZGU/u+Wg=; b=kPcr6MZ5tt2xoybTQcRsLOMwfnoV6YJyNmFPxvGDoCHptC4akaVl1K7hej/w+msi77d3ai6KU6vd0PGhX/M1RbH8cwOqxrI27PFZaBvmuylL8mAlbXZqMt8DCjaKz3E06TFvbzUBsImlfoPHUpT52zp7PNgXOobPSCN4kR2CbwI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902736546326.72539440798505; Mon, 11 Aug 2025 01:58:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKN-00045o-8G; Mon, 11 Aug 2025 04:56:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKJ-000457-DM for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:19 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKA-0003VX-F2 for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:18 -0400 Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pMk35hJz6M584; Mon, 11 Aug 2025 16:53:54 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id EF661140121; Mon, 11 Aug 2025 16:55:48 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:48 +0200 To: , , , , CC: , Subject: [PATCH v6 1/8] qapi: cxl: Refactor CXL event injection for common commands arguments Date: Mon, 11 Aug 2025 09:55:23 +0100 Message-ID: <20250811085530.2263-2-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902738831116600 Content-Type: text/plain; charset="utf-8" From: Shiju Jose Refactor CXL event injection to use struct for common command arguments. Suggested-by: Markus Armbruster Signed-off-by: Shiju Jose --- qapi/cxl.json | 89 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/qapi/cxl.json b/qapi/cxl.json index 8f2e9237b1..0dabf07536 100644 --- a/qapi/cxl.json +++ b/qapi/cxl.json @@ -29,11 +29,10 @@ } =20 ## -# @cxl-inject-general-media-event: +# @CXLCommonEventBase: # -# Inject an event record for a General Media Event (CXL r3.0 -# 8.2.9.2.1.1). This event type is reported via one of the event logs -# specified via the log parameter. +# Common event base for a CXL Event (CXL r3.0 8.2.9.2.1 +# Table 8-42 Common Event Record Format). # # @path: CXL type 3 device canonical QOM path # @@ -42,6 +41,16 @@ # @flags: Event Record Flags. See CXL r3.0 Table 8-42 Common Event # Record Format, Event Record Flags for subfield definitions. # +# Since: 8.1 +## +{ 'struct': 'CXLCommonEventBase', + 'data': { 'path': 'str', 'log': 'CxlEventLog', 'flags': 'uint8' } } + +## +# @CXLGeneralMediaEvent: +# +# Event record for a General Media Event (CXL r3.0 8.2.9.2.1.1). +# # @dpa: Device Physical Address (relative to @path device). Note # lower bits include some flags. See CXL r3.0 Table 8-43 General # Media Event Record, Physical Address. @@ -72,26 +81,29 @@ # # Since: 8.1 ## -{ 'command': 'cxl-inject-general-media-event', - 'data': { 'path': 'str', 'log': 'CxlEventLog', 'flags': 'uint8', - 'dpa': 'uint64', 'descriptor': 'uint8', +{ 'struct': 'CXLGeneralMediaEvent', + 'base': 'CXLCommonEventBase', + 'data': { 'dpa': 'uint64', 'descriptor': 'uint8', 'type': 'uint8', 'transaction-type': 'uint8', '*channel': 'uint8', '*rank': 'uint8', '*device': 'uint32', '*component-id': 'str' } } =20 ## -# @cxl-inject-dram-event: -# -# Inject an event record for a DRAM Event (CXL r3.0 8.2.9.2.1.2). -# This event type is reported via one of the event logs specified via -# the log parameter. +# @cxl-inject-general-media-event: # -# @path: CXL type 3 device canonical QOM path +# Inject an event record for a General Media Event (CXL r3.0 +# 8.2.9.2.1.1). This event type is reported via one of the event +# logs specified via the log parameter. # -# @log: Event log to add the event to +# Since: 8.1 +## +{ 'command': 'cxl-inject-general-media-event', + 'data': 'CXLGeneralMediaEvent' } + +## +# @CXLDRAMEvent: # -# @flags: Event Record Flags. See CXL r3.0 Table 8-42 Common Event -# Record Format, Event Record Flags for subfield definitions. +# Event record for a DRAM Event (CXL r3.0 8.2.9.2.1.2). # # @dpa: Device Physical Address (relative to @path device). Note # lower bits include some flags. See CXL r3.0 Table 8-44 DRAM @@ -131,9 +143,9 @@ # # Since: 8.1 ## -{ 'command': 'cxl-inject-dram-event', - 'data': { 'path': 'str', 'log': 'CxlEventLog', 'flags': 'uint8', - 'dpa': 'uint64', 'descriptor': 'uint8', +{ 'struct': 'CXLDRAMEvent', + 'base': 'CXLCommonEventBase', + 'data': { 'dpa': 'uint64', 'descriptor': 'uint8', 'type': 'uint8', 'transaction-type': 'uint8', '*channel': 'uint8', '*rank': 'uint8', '*nibble-mask': 'uint32= ', '*bank-group': 'uint8', '*bank': 'uint8', '*row': 'uint32', @@ -141,18 +153,21 @@ }} =20 ## -# @cxl-inject-memory-module-event: +# @cxl-inject-dram-event: # -# Inject an event record for a Memory Module Event (CXL r3.0 -# 8.2.9.2.1.3). This event includes a copy of the Device Health info -# at the time of the event. +# Inject an event record for a DRAM Event (CXL r3.0 8.2.9.2.1.2). +# This event type is reported via one of the event logs +# specified via the log parameter. # -# @path: CXL type 3 device canonical QOM path +# Since: 8.1 +## +{ 'command': 'cxl-inject-dram-event', + 'data': 'CXLDRAMEvent' } + +## +# @CXLMemModuleEvent: # -# @log: Event Log to add the event to -# -# @flags: Event Record Flags. See CXL r3.0 Table 8-42 Common Event -# Record Format, Event Record Flags for subfield definitions. +# Event record for a Memory Module Event (CXL r3.0 8.2.9.2.1.3). # # @type: Device Event Type. See CXL r3.0 Table 8-45 Memory Module # Event Record for bit definitions for bit definiions. @@ -183,9 +198,9 @@ # # Since: 8.1 ## -{ 'command': 'cxl-inject-memory-module-event', - 'data': { 'path': 'str', 'log': 'CxlEventLog', 'flags' : 'uint8', - 'type': 'uint8', 'health-status': 'uint8', +{ 'struct': 'CXLMemModuleEvent', + 'base': 'CXLCommonEventBase', + 'data': { 'type': 'uint8', 'health-status': 'uint8', 'media-status': 'uint8', 'additional-status': 'uint8', 'life-used': 'uint8', 'temperature' : 'int16', 'dirty-shutdown-count': 'uint32', @@ -193,6 +208,18 @@ 'corrected-persistent-error-count': 'uint32' }} =20 +## +# @cxl-inject-memory-module-event: +# +# Inject an event record for a DRAM Event (CXL r3.0 8.2.9.2.1.3) +# This event type is reported via one of the event logs +# specified via the log parameter. +# +# Since: 8.1 +## +{ 'command': 'cxl-inject-memory-module-event', + 'data': 'CXLMemModuleEvent' } + ## # @cxl-inject-poison: # --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902712; cv=none; d=zohomail.com; s=zohoarc; b=lXjTE5dQhUVB4u5QEB+nAiJMNszJKXccqYjtdSBobkchH4e5KaRjvtci0joEGcP9KniQ+jiX9dmta/bbXXVPRiD2Lieja8sKHD/mjmQ5r7I8sWUT474/yVtSPJGZ4lMoSOfK97ItIufwCuLPzDpPWQKMl7Og9n7ryGlGcUY7xTc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902712; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=QxDWQ1jEqQPHOgPv/XsGjlqrRZnUuYHbT+btcx1cJfA=; b=YymseRcnC9Wv0zWjLYZq3Awtl/AViPBzi+N/qT8G8K8e7e3Jk1j8eddiUPmyS/qn2S64vJP9+cvNtgzaPo4p0Wt2jINsB7/L3FNZY49DT/bPCAPguHBN9fOLGV4frLfwpX0OCGS2aM0jka+11WZo5xMkOJEK2ueJFQ5V5J54lDg= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902712567536.3621426145975; Mon, 11 Aug 2025 01:58:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKN-00045m-7p; Mon, 11 Aug 2025 04:56:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKH-00044V-7P for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:17 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vc-IQ for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:16 -0400 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pLz4pN1z6L5S4; Mon, 11 Aug 2025 16:53:15 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id 8A9051402F3; Mon, 11 Aug 2025 16:55:49 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:48 +0200 To: , , , , CC: , Subject: [PATCH v6 2/8] hw/cxl/events: Update for rev3.2 common event record format Date: Mon, 11 Aug 2025 09:55:24 +0100 Message-ID: <20250811085530.2263-3-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902714206124100 Content-Type: text/plain; charset="utf-8" From: Shiju Jose CXL spec 3.2 section 8.2.9.2.1 Table 8-55, Common Event Record format has updated with optional Maintenance Operation Subclass, LD ID and ID of the device head information. Add updates for the above optional parameters in the related CXL events reporting and in the QMP commands to inject CXL events. Signed-off-by: Shiju Jose --- hw/cxl/cxl-events.c | 3 +- hw/cxl/cxl-mailbox-utils.c | 3 +- hw/mem/cxl_type3.c | 70 ++++++++++++++++++++++++++++++++----- hw/mem/cxl_type3_stubs.c | 24 +++++++++++-- include/hw/cxl/cxl_device.h | 7 +++- include/hw/cxl/cxl_events.h | 15 ++++++-- qapi/cxl.json | 20 ++++++++--- 7 files changed, 121 insertions(+), 21 deletions(-) diff --git a/hw/cxl/cxl-events.c b/hw/cxl/cxl-events.c index 724055f2cf..673154db29 100644 --- a/hw/cxl/cxl-events.c +++ b/hw/cxl/cxl-events.c @@ -273,7 +273,8 @@ void cxl_create_dc_event_records_for_extents(CXLType3De= v *ct3d, &dynamic_capacity_uuid, (1 << CXL_EVENT_TYPE_INFO), sizeof(event_rec), - cxl_device_get_timestamp(&ct3d->cxl_dstate)); + cxl_device_get_timestamp(&ct3d->cxl_dstate), + 0, 0, 0, 0, 0, 0, 0, 0); event_rec.type =3D type; event_rec.validity_flags =3D 1; event_rec.host_id =3D 0; diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index 43a0d503aa..8f62ea9b54 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -3457,7 +3457,8 @@ static CXLRetCode cmd_fm_set_dc_region_config(const s= truct cxl_cmd *cmd, &dynamic_capacity_uuid, (1 << CXL_EVENT_TYPE_INFO), sizeof(dcEvent), - cxl_device_get_timestamp(&ct3d->cxl_dstate)); + cxl_device_get_timestamp(&ct3d->cxl_dstate), + 0, 0, 0, 0, 0, 0, 0, 0); dcEvent.type =3D DC_EVENT_REGION_CONFIG_UPDATED; dcEvent.validity_flags =3D 1; dcEvent.host_id =3D 0; diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 7676d785c2..aa6e5c1a08 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -1592,12 +1592,39 @@ void qmp_cxl_inject_correctable_error(const char *p= ath, CxlCorErrorType type, =20 void cxl_assign_event_header(CXLEventRecordHdr *hdr, const QemuUUID *uuid, uint32_t flags, - uint8_t length, uint64_t timestamp) + uint8_t length, uint64_t timestamp, + bool has_maint_op_class, uint8_t maint_op_cla= ss, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id) { - st24_le_p(&hdr->flags, flags); hdr->length =3D length; memcpy(&hdr->id, uuid, sizeof(hdr->id)); stq_le_p(&hdr->timestamp, timestamp); + + if (has_maint_op_class) { + hdr->maint_op_class =3D maint_op_class; + } else { + hdr->maint_op_class =3D 0; + } + + if (has_maint_op_subclass) { + flags |=3D CXL_EVENT_REC_FLAGS_MAINT_OP_SUBCLASS_VALID; + hdr->maint_op_subclass =3D maint_op_subclass; + } + + if (has_ld_id) { + flags |=3D CXL_EVENT_REC_FLAGS_LD_ID_VALID; + stw_le_p(&hdr->ld_id, ld_id); + } + + if (has_head_id) { + flags |=3D CXL_EVENT_REC_FLAGS_HEAD_ID_VALID; + hdr->head_id =3D head_id; + } + + st24_le_p(&hdr->flags, flags); } =20 static const QemuUUID gen_media_uuid =3D { @@ -1637,7 +1664,13 @@ static int ct3d_qmp_cxl_event_log_enc(CxlEventLog lo= g) } /* Component ID is device specific. Define this as a string. */ void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log, - uint8_t flags, uint64_t dpa, + uint32_t flags, bool has_maint_op_= class, + uint8_t maint_op_class, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id, + uint64_t dpa, uint8_t descriptor, uint8_t type, uint8_t transaction_type, bool has_channel, uint8_t channel, @@ -1675,7 +1708,10 @@ void qmp_cxl_inject_general_media_event(const char *= path, CxlEventLog log, =20 memset(&gem, 0, sizeof(gem)); cxl_assign_event_header(hdr, &gen_media_uuid, flags, sizeof(gem), - cxl_device_get_timestamp(&ct3d->cxl_dstate)); + cxl_device_get_timestamp(&ct3d->cxl_dstate), + has_maint_op_class, maint_op_class, + has_maint_op_subclass, maint_op_subclass, + has_ld_id, ld_id, has_head_id, head_id); =20 stq_le_p(&gem.phys_addr, dpa); gem.descriptor =3D descriptor; @@ -1719,7 +1755,13 @@ void qmp_cxl_inject_general_media_event(const char *= path, CxlEventLog log, #define CXL_DRAM_VALID_COLUMN BIT(6) #define CXL_DRAM_VALID_CORRECTION_MASK BIT(7) =20 -void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, uint8_t = flags, +void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, + uint32_t flags, + bool has_maint_op_class, uint8_t maint_op_c= lass, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id, uint64_t dpa, uint8_t descriptor, uint8_t type, uint8_t transaction_type, bool has_channel, uint8_t channel, @@ -1762,7 +1804,10 @@ void qmp_cxl_inject_dram_event(const char *path, Cxl= EventLog log, uint8_t flags, =20 memset(&dram, 0, sizeof(dram)); cxl_assign_event_header(hdr, &dram_uuid, flags, sizeof(dram), - cxl_device_get_timestamp(&ct3d->cxl_dstate)); + cxl_device_get_timestamp(&ct3d->cxl_dstate), + has_maint_op_class, maint_op_class, + has_maint_op_subclass, maint_op_subclass, + has_ld_id, ld_id, has_head_id, head_id); stq_le_p(&dram.phys_addr, dpa); dram.descriptor =3D descriptor; dram.type =3D type; @@ -1822,7 +1867,13 @@ void qmp_cxl_inject_dram_event(const char *path, Cxl= EventLog log, uint8_t flags, } =20 void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log, - uint8_t flags, uint8_t type, + uint32_t flags, bool has_maint_op_= class, + uint8_t maint_op_class, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id, + uint8_t type, uint8_t health_status, uint8_t media_status, uint8_t additional_status, @@ -1861,7 +1912,10 @@ void qmp_cxl_inject_memory_module_event(const char *= path, CxlEventLog log, =20 memset(&module, 0, sizeof(module)); cxl_assign_event_header(hdr, &memory_module_uuid, flags, sizeof(module= ), - cxl_device_get_timestamp(&ct3d->cxl_dstate)); + cxl_device_get_timestamp(&ct3d->cxl_dstate), + has_maint_op_class, maint_op_class, + has_maint_op_subclass, maint_op_subclass, + has_ld_id, ld_id, has_head_id, head_id); =20 module.type =3D type; module.health_status =3D health_status; diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c index c1a5e4a7c1..91b1478114 100644 --- a/hw/mem/cxl_type3_stubs.c +++ b/hw/mem/cxl_type3_stubs.c @@ -14,7 +14,13 @@ #include "qapi/qapi-commands-cxl.h" =20 void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log, - uint8_t flags, uint64_t dpa, + uint32_t flags, bool has_maint_op_= class, + uint8_t maint_op_class, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id, + uint64_t dpa, uint8_t descriptor, uint8_t type, uint8_t transaction_type, bool has_channel, uint8_t channel, @@ -23,7 +29,13 @@ void qmp_cxl_inject_general_media_event(const char *path= , CxlEventLog log, const char *component_id, Error **errp) {} =20 -void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, uint8_t = flags, +void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, + uint32_t flags, + bool has_maint_op_class, uint8_t maint_op_c= lass, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id, uint64_t dpa, uint8_t descriptor, uint8_t type, uint8_t transaction_type, bool has_channel, uint8_t channel, @@ -38,7 +50,13 @@ void qmp_cxl_inject_dram_event(const char *path, CxlEven= tLog log, uint8_t flags, Error **errp) {} =20 void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log, - uint8_t flags, uint8_t type, + uint32_t flags, bool has_maint_op_= class, + uint8_t maint_op_class, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id, + uint8_t type, uint8_t health_status, uint8_t media_status, uint8_t additional_status, diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index fdee60b977..b77b6b2499 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -723,7 +723,12 @@ bool ct3_test_region_block_backed(CXLType3Dev *ct3d, u= int64_t dpa, uint64_t len); void cxl_assign_event_header(CXLEventRecordHdr *hdr, const QemuUUID *uuid, uint32_t flags, - uint8_t length, uint64_t timestamp); + uint8_t length, uint64_t timestamp, + bool has_maint_op_class, uint8_t maint_op_cla= ss, + bool has_maint_op_subclass, + uint8_t maint_op_subclass, + bool has_ld_id, uint16_t ld_id, + bool has_head_id, uint8_t head_id); void cxl_create_dc_event_records_for_extents(CXLType3Dev *ct3d, CXLDCEventType type, CXLDCExtentRaw extents[], diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 758b075a64..4d9cfdb621 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -29,9 +29,15 @@ typedef enum CXLEventLogType { =20 /* * Common Event Record Format - * CXL r3.1 section 8.2.9.2.1: Event Records; Table 8-43 + * CXL r3.2 section 8.2.10.2.1: Event Records; Table 8-55 */ -#define CXL_EVENT_REC_HDR_RES_LEN 0xf +#define CXL_EVENT_REC_FLAGS_PERMANENT_COND BIT(2) +#define CXL_EVENT_REC_FLAGS_MAINT_NEEDED BIT(3) +#define CXL_EVENT_REC_FLAGS_PERF_DEGRADED BIT(4) +#define CXL_EVENT_REC_FLAGS_HW_REPLACEMENT_NEEDED BIT(5) +#define CXL_EVENT_REC_FLAGS_MAINT_OP_SUBCLASS_VALID BIT(6) +#define CXL_EVENT_REC_FLAGS_LD_ID_VALID BIT(7) +#define CXL_EVENT_REC_FLAGS_HEAD_ID_VALID BIT(8) typedef struct CXLEventRecordHdr { QemuUUID id; uint8_t length; @@ -40,7 +46,10 @@ typedef struct CXLEventRecordHdr { uint16_t related_handle; uint64_t timestamp; uint8_t maint_op_class; - uint8_t reserved[CXL_EVENT_REC_HDR_RES_LEN]; + uint8_t maint_op_subclass; + uint16_t ld_id; + uint8_t head_id; + uint8_t reserved[0xb]; } QEMU_PACKED CXLEventRecordHdr; =20 #define CXL_EVENT_RECORD_DATA_LENGTH 0x50 diff --git a/qapi/cxl.json b/qapi/cxl.json index 0dabf07536..44ae93ddb6 100644 --- a/qapi/cxl.json +++ b/qapi/cxl.json @@ -31,20 +31,32 @@ ## # @CXLCommonEventBase: # -# Common event base for a CXL Event (CXL r3.0 8.2.9.2.1 -# Table 8-42 Common Event Record Format). +# Common event base for a CXL Event (CXL r3.2 8.2.10.2.1 +# Table 8-55 Common Event Record Format). # # @path: CXL type 3 device canonical QOM path # # @log: event log to add the event to # -# @flags: Event Record Flags. See CXL r3.0 Table 8-42 Common Event +# @flags: Event Record Flags. See CXL r3.2 Table 8-55 Common Event # Record Format, Event Record Flags for subfield definitions. # +# @maint-op-class: Maintenance operation class the device requests to +# initiate. +# +# @maint-op-subclass: Maintenance operation subclass the device +# requests to initiate. +# +# @ld-id: LD ID of LD from where the event originated. +# +# @head-id: ID of the device head from where the event originated. +# # Since: 8.1 ## { 'struct': 'CXLCommonEventBase', - 'data': { 'path': 'str', 'log': 'CxlEventLog', 'flags': 'uint8' } } + 'data': { 'path': 'str', 'log': 'CxlEventLog', 'flags': 'uint32', + '*maint-op-class':'uint8', '*maint-op-subclass':'uint8', + '*ld-id':'uint16', '*head-id':'uint8' } } =20 ## # @CXLGeneralMediaEvent: --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902679; cv=none; d=zohomail.com; s=zohoarc; b=Swq6kYCKWHo+VLYS/jfAiFdzCkQVTvIhq+TvVmM1TgIFO/hGMm8NFc06a0sBZsXMUemK87/IPZfd4/WzPQZEE3vok3nv/CPgg2eBXqs5zgCTYQIfieX/UlFAbkC88twspfqivgLLBofEvheJM3OIH+wwL8vGhYDdFUXQMHaHKek= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902679; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=x0fhKIIYQV2XVrvGyU2DgHTYxz+TUgGvNi+lRMKfrEo=; b=HJah5Y6RGtjxdDHhc6yRBdW5cFcg5QgTrf9yNX+LzqG5V/f5gddFxJ5zY1Wg+Cuu7ZSYFSbgUcK2ixCtkva9t8akKtFeKOQgOIrwMstnmZ3w0m5IpK+9uQcjLVaFAM+Q2UBLbF9FjmlF/ZPhci89kixg3a1oQVzr6ReGsMsyLk8= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902679638333.7735031523018; Mon, 11 Aug 2025 01:57:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKS-00047M-Ik; Mon, 11 Aug 2025 04:56:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKH-00044w-S1 for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:17 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vj-6T for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:17 -0400 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pM02jSFz6L5SZ; Mon, 11 Aug 2025 16:53:16 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id 48504140278; Mon, 11 Aug 2025 16:55:50 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:49 +0200 To: , , , , CC: , Subject: [PATCH v6 3/8] hw/cxl/events: Updates for rev3.2 general media event record Date: Mon, 11 Aug 2025 09:55:25 +0100 Message-ID: <20250811085530.2263-4-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902681877124100 Content-Type: text/plain; charset="utf-8" From: Shiju Jose CXL spec rev3.2 section 8.2.10.2.1.1 Table 8-57, general media event table has updated with following new fields. 1. Advanced Programmable Corrected Memory Error Threshold Event Flags 2. Corrected Memory Error Count at Event 3. Memory Event Sub-Type 4. Support for component ID in the PLDM format. Add updates for the above spec changes in the CXL general media event reporting and QMP command to inject general media event. Signed-off-by: Shiju Jose --- hw/mem/cxl_type3.c | 29 +++++++++++++++++++++++++++++ hw/mem/cxl_type3_stubs.c | 6 ++++++ include/hw/cxl/cxl_events.h | 7 +++++-- qapi/cxl.json | 15 ++++++++++++++- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index aa6e5c1a08..1a8ca533fa 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -1646,6 +1646,11 @@ static const QemuUUID memory_module_uuid =3D { #define CXL_GMER_VALID_RANK BIT(1) #define CXL_GMER_VALID_DEVICE BIT(2) #define CXL_GMER_VALID_COMPONENT BIT(3) +#define CXL_GMER_VALID_COMPONENT_ID_FORMAT BIT(4) + +#define CXL_GMER_EV_DESC_UCE BIT(0) +#define CXL_GMER_EV_DESC_THRESHOLD_EVENT BIT(1) +#define CXL_GMER_EV_DESC_POISON_LIST_OVERFLOW_EVENT BIT(2) =20 static int ct3d_qmp_cxl_event_log_enc(CxlEventLog log) { @@ -1677,6 +1682,12 @@ void qmp_cxl_inject_general_media_event(const char *= path, CxlEventLog log, bool has_rank, uint8_t rank, bool has_device, uint32_t device, const char *component_id, + bool has_comp_id_pldm, + bool is_comp_id_pldm, + bool has_cme_ev_flags, + uint8_t cme_ev_flags, + bool has_cme_count, uint32_t cme_c= ount, + uint8_t sub_type, Error **errp) { Object *obj =3D object_resolve_path(path, NULL); @@ -1737,10 +1748,28 @@ void qmp_cxl_inject_general_media_event(const char = *path, CxlEventLog log, strncpy((char *)gem.component_id, component_id, sizeof(gem.component_id) - 1); valid_flags |=3D CXL_GMER_VALID_COMPONENT; + if (has_comp_id_pldm && is_comp_id_pldm) { + valid_flags |=3D CXL_GMER_VALID_COMPONENT_ID_FORMAT; + } } =20 stw_le_p(&gem.validity_flags, valid_flags); =20 + if (has_cme_ev_flags) { + gem.cme_ev_flags =3D cme_ev_flags; + } else { + gem.cme_ev_flags =3D 0; + } + + if (has_cme_count) { + descriptor |=3D CXL_GMER_EV_DESC_THRESHOLD_EVENT; + st24_le_p(gem.cme_count, cme_count); + } else { + st24_le_p(gem.cme_count, 0); + } + + gem.sub_type =3D sub_type; + if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&gem)) { cxl_event_irq_assert(ct3d); } diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c index 91b1478114..2047e97846 100644 --- a/hw/mem/cxl_type3_stubs.c +++ b/hw/mem/cxl_type3_stubs.c @@ -27,6 +27,12 @@ void qmp_cxl_inject_general_media_event(const char *path= , CxlEventLog log, bool has_rank, uint8_t rank, bool has_device, uint32_t device, const char *component_id, + bool has_comp_id_pldm, + bool is_comp_id_pldm, + bool has_cme_ev_flags, + uint8_t cme_ev_flags, + bool has_cme_count, uint32_t cme_c= ount, + uint8_t sub_type, Error **errp) {} =20 void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 4d9cfdb621..352f9891bd 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -115,10 +115,10 @@ typedef struct CXLEventInterruptPolicy { =20 /* * General Media Event Record - * CXL r3.1 Section 8.2.9.2.1.1; Table 8-45 + * CXL r3.2 Section 8.2.10.2.1.1; Table 8-57 */ #define CXL_EVENT_GEN_MED_COMP_ID_SIZE 0x10 -#define CXL_EVENT_GEN_MED_RES_SIZE 0x2e +#define CXL_EVENT_GEN_MED_RES_SIZE 0x29 typedef struct CXLEventGenMedia { CXLEventRecordHdr hdr; uint64_t phys_addr; @@ -130,6 +130,9 @@ typedef struct CXLEventGenMedia { uint8_t rank; uint8_t device[3]; uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; + uint8_t cme_ev_flags; + uint8_t cme_count[3]; + uint8_t sub_type; uint8_t reserved[CXL_EVENT_GEN_MED_RES_SIZE]; } QEMU_PACKED CXLEventGenMedia; =20 diff --git a/qapi/cxl.json b/qapi/cxl.json index 44ae93ddb6..a245632f92 100644 --- a/qapi/cxl.json +++ b/qapi/cxl.json @@ -91,6 +91,16 @@ # @component-id: Device specific component identifier for the event. # May describe a field replaceable sub-component of the device. # +# @is-comp-id-pldm: This flag specifies whether the device-specific +# component identifier format follows PLDM. +# +# @cme-ev-flags: Advanced programmable corrected memory error +# threshold event flags. +# +# @cme-count: Corrected memory error count at event. +# +# @sub-type: Memory event sub-type. +# # Since: 8.1 ## { 'struct': 'CXLGeneralMediaEvent', @@ -98,7 +108,10 @@ 'data': { 'dpa': 'uint64', 'descriptor': 'uint8', 'type': 'uint8', 'transaction-type': 'uint8', '*channel': 'uint8', '*rank': 'uint8', - '*device': 'uint32', '*component-id': 'str' } } + '*device': 'uint32', '*component-id': 'str', + '*is-comp-id-pldm':'bool', + '*cme-ev-flags':'uint8', '*cme-count':'uint32', + 'sub-type':'uint8' } } =20 ## # @cxl-inject-general-media-event: --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902647; cv=none; d=zohomail.com; s=zohoarc; b=lR3fAoLClOfWfuph9J+XyWxSNVaq4g6R8e+69Nf7IjD4izg1/AXRfp01qkF8wbHNlHcz2JToKL4pvPxGVJ+1nF4MjxVZRC5WFkZvXeHAYVvFWz2G1Vlcw0LgbrfWAkueWdqRmyu4iUokxGlBf8HlbHXSmkpSnxbccaPXmUUzVHg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902647; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=cBd0zQ+0ZPzmeqjkNbeog1gkivl4Y27sKiA6ux2E2Mg=; b=APOOXyATnEVpA3x3jgkjkCpyflkWo2Ty9H77R9Thf2aCPSRVrZoMAh+BP2yE3ouP4yLOwhHfnHrzVg7sDOEAhawzXFnN3OgEjOpBOhneg2389Bd3edpkTTCJj5s9bnrG6rqw3wZf/nWiKkYZ9TvJNTm6Nx2DpBHIu/sO4QNoxq0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175490264783241.9087210779403; Mon, 11 Aug 2025 01:57:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKK-000453-PU; Mon, 11 Aug 2025 04:56:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKE-00043x-6O for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:15 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vp-6S for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:12 -0400 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pMm3BLrz6M57w; Mon, 11 Aug 2025 16:53:56 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id 016F41404C4; Mon, 11 Aug 2025 16:55:51 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:50 +0200 To: , , , , CC: , Subject: [PATCH v6 4/8] hw/cxl/events: Updates for rev3.2 DRAM event record Date: Mon, 11 Aug 2025 09:55:26 +0100 Message-ID: <20250811085530.2263-5-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902669965124100 Content-Type: text/plain; charset="utf-8" From: Shiju Jose CXL spec rev3.2 section 8.2.10.2.1.2 Table 8-58, DRAM event record has updated with following new fields. 1. Component Identifier 2. Sub-channel of the memory event location 3. Advanced Programmable Corrected Memory Error Threshold Event Flags 4. Corrected Volatile Memory Error Count at Event 5. Memory Event Sub-Type Add updates for the above spec changes in the CXL DRAM event reporting and QMP command to inject DRAM event. Signed-off-by: Shiju Jose --- hw/mem/cxl_type3.c | 42 +++++++++++++++++++++++++++++++++++++ hw/mem/cxl_type3_stubs.c | 7 +++++++ include/hw/cxl/cxl_events.h | 9 ++++++-- qapi/cxl.json | 21 ++++++++++++++++++- 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 1a8ca533fa..c359a8b65c 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -1783,6 +1783,13 @@ void qmp_cxl_inject_general_media_event(const char *= path, CxlEventLog log, #define CXL_DRAM_VALID_ROW BIT(5) #define CXL_DRAM_VALID_COLUMN BIT(6) #define CXL_DRAM_VALID_CORRECTION_MASK BIT(7) +#define CXL_DRAM_VALID_COMPONENT BIT(8) +#define CXL_DRAM_VALID_COMPONENT_ID_FORMAT BIT(9) +#define CXL_DRAM_VALID_SUB_CHANNEL BIT(10) + +#define CXL_DRAM_EV_DESC_UCE BIT(0) +#define CXL_DRAM_EV_DESC_THRESHOLD_EVENT BIT(1) +#define CXL_DRAM_EV_DESC_POISON_LIST_OVERFLOW_EVENT BIT(2) =20 void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, uint32_t flags, @@ -1802,6 +1809,12 @@ void qmp_cxl_inject_dram_event(const char *path, Cxl= EventLog log, bool has_column, uint16_t column, bool has_correction_mask, uint64List *correction_mask, + const char *component_id, + bool has_comp_id_pldm, bool is_comp_id_pldm, + bool has_sub_channel, uint8_t sub_channel, + bool has_cme_ev_flags, uint8_t cme_ev_flags, + bool has_cvme_count, uint32_t cvme_count, + uint8_t sub_type, Error **errp) { Object *obj =3D object_resolve_path(path, NULL); @@ -1888,6 +1901,35 @@ void qmp_cxl_inject_dram_event(const char *path, Cxl= EventLog log, valid_flags |=3D CXL_DRAM_VALID_CORRECTION_MASK; } =20 + if (component_id) { + strncpy((char *)dram.component_id, component_id, + sizeof(dram.component_id) - 1); + valid_flags |=3D CXL_DRAM_VALID_COMPONENT; + if (has_comp_id_pldm && is_comp_id_pldm) { + valid_flags |=3D CXL_DRAM_VALID_COMPONENT_ID_FORMAT; + } + } + + if (has_sub_channel) { + dram.sub_channel =3D sub_channel; + valid_flags |=3D CXL_DRAM_VALID_SUB_CHANNEL; + } + + if (has_cme_ev_flags) { + dram.cme_ev_flags =3D cme_ev_flags; + } else { + dram.cme_ev_flags =3D 0; + } + + if (has_cvme_count) { + descriptor |=3D CXL_DRAM_EV_DESC_THRESHOLD_EVENT; + st24_le_p(dram.cvme_count, cvme_count); + } else { + st24_le_p(dram.cvme_count, 0); + } + + dram.sub_type =3D sub_type; + stw_le_p(&dram.validity_flags, valid_flags); =20 if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&dram)) { diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c index 2047e97846..231dda263f 100644 --- a/hw/mem/cxl_type3_stubs.c +++ b/hw/mem/cxl_type3_stubs.c @@ -53,6 +53,13 @@ void qmp_cxl_inject_dram_event(const char *path, CxlEven= tLog log, bool has_column, uint16_t column, bool has_correction_mask, uint64List *correction_mask, + const char *component_id, + bool has_comp_id_pldm, + bool is_comp_id_pldm, + bool has_sub_channel, uint8_t sub_channel, + bool has_cme_ev_flags, uint8_t cme_ev_flags, + bool has_cvme_count, uint32_t cvme_count, + uint8_t sub_type, Error **errp) {} =20 void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log, diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 352f9891bd..a3c5f2ec20 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -138,7 +138,7 @@ typedef struct CXLEventGenMedia { =20 /* * DRAM Event Record - * CXL r3.1 Section 8.2.9.2.1.2: Table 8-46 + * CXL r3.2 Section 8.2.10.2.1.2: Table 8-58 * All fields little endian. */ typedef struct CXLEventDram { @@ -156,7 +156,12 @@ typedef struct CXLEventDram { uint8_t row[3]; uint16_t column; uint64_t correction_mask[4]; - uint8_t reserved[0x17]; + uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; + uint8_t sub_channel; + uint8_t cme_ev_flags; + uint8_t cvme_count[3]; + uint8_t sub_type; + uint8_t reserved; } QEMU_PACKED CXLEventDram; =20 /* diff --git a/qapi/cxl.json b/qapi/cxl.json index a245632f92..c2f8b03224 100644 --- a/qapi/cxl.json +++ b/qapi/cxl.json @@ -166,6 +166,21 @@ # @correction-mask: Bits within each nibble. Used in order of bits # set in the nibble-mask. Up to 4 nibbles may be covered. # +# @component-id: Device specific component identifier for the event. +# May describe a field replaceable sub-component of the device. +# +# @is-comp-id-pldm: This flag specifies whether the device-specific +# component identifier format follows PLDM. +# +# @sub-channel: The sub-channel of the memory event location. +# +# @cme-ev-flags: Advanced programmable corrected memory error +# threshold event flags. +# +# @cvme-count: Corrected volatile memory error count at event. +# +# @sub-type: Memory event sub-type. +# # Since: 8.1 ## { 'struct': 'CXLDRAMEvent', @@ -174,7 +189,11 @@ 'type': 'uint8', 'transaction-type': 'uint8', '*channel': 'uint8', '*rank': 'uint8', '*nibble-mask': 'uint32= ', '*bank-group': 'uint8', '*bank': 'uint8', '*row': 'uint32', - '*column': 'uint16', '*correction-mask': [ 'uint64' ] + '*column': 'uint16', '*correction-mask': [ 'uint64' ], + '*component-id': 'str', '*is-comp-id-pldm':'bool', + '*sub-channel':'uint8', + '*cme-ev-flags':'uint8', '*cvme-count':'uint32', + 'sub-type':'uint8' }} =20 ## --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902648; cv=none; d=zohomail.com; s=zohoarc; b=SLBIFGnBAJvwWKIjxNkqn2l7CzlpaU+eUXYFSsDPwBMLml0k9QvJxGz5xhcMSOfjvnpiisvUxoh2DW1uSMf07QHIhCOD4wUXJzmFqtNKFx5x24AnCMnU83g8jwk8QEBHoC+gVhog9HDmA2JzHNO3oIgtgrYj3KmPUf1f8J+L1tY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902648; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=3f0zygTu2da+/Imc39m3he9+KnRpu+zIi2xxV7VcTuI=; b=byAP84wrDFg/FFG/I3ywrVihdIsrNsWQecXPs249hUdI0YTsOHTCJJ0pGYJ0a4iGokFKmvAUtWo2cumiLx+Oz96Jjsxa3LaxVgOcKXL2/VQ1t7Z7TkXHxOOdbNLAX/4V9XjBmXDFLlzONarvX8/O2CWhdWM8hRm92NmBmHgiT+s= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902648289179.63099388093474; Mon, 11 Aug 2025 01:57:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKK-00044z-PE; Mon, 11 Aug 2025 04:56:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKE-00043y-8q for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:15 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vr-6S for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:12 -0400 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pM15xjBz6L59K; Mon, 11 Aug 2025 16:53:17 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id AFC011402F4; Mon, 11 Aug 2025 16:55:51 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:51 +0200 To: , , , , CC: , Subject: [PATCH v6 5/8] hw/cxl/events: Updates for rev3.2 memory module event record Date: Mon, 11 Aug 2025 09:55:27 +0100 Message-ID: <20250811085530.2263-6-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902651558124100 Content-Type: text/plain; charset="utf-8" From: Shiju Jose CXL spec rev3.2 section 8.2.10.2.1.3 Table 8-50, memory module event record has updated with following new fields. 1. Validity Flags 2. Component Identifier 3. Device Event Sub-Type Add updates for the above spec changes in the CXL memory module event reporting and QMP command to inject memory module event. Signed-off-by: Shiju Jose --- hw/mem/cxl_type3.c | 20 ++++++++++++++++++++ hw/mem/cxl_type3_stubs.c | 4 ++++ include/hw/cxl/cxl_events.h | 7 +++++-- qapi/cxl.json | 12 +++++++++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index c359a8b65c..c0578af972 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -1937,6 +1937,9 @@ void qmp_cxl_inject_dram_event(const char *path, CxlE= ventLog log, } } =20 +#define CXL_MMER_VALID_COMPONENT BIT(0) +#define CXL_MMER_VALID_COMPONENT_ID_FORMAT BIT(1) + void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log, uint32_t flags, bool has_maint_op_= class, uint8_t maint_op_class, @@ -1953,11 +1956,16 @@ void qmp_cxl_inject_memory_module_event(const char = *path, CxlEventLog log, uint32_t dirty_shutdown_count, uint32_t corrected_volatile_error_= count, uint32_t corrected_persist_error_c= ount, + const char *component_id, + bool has_comp_id_pldm, + bool is_comp_id_pldm, + uint8_t sub_type, Error **errp) { Object *obj =3D object_resolve_path(path, NULL); CXLEventMemoryModule module; CXLEventRecordHdr *hdr =3D &module.hdr; + uint16_t valid_flags =3D 0; CXLDeviceState *cxlds; CXLType3Dev *ct3d; uint8_t enc_log; @@ -2000,6 +2008,18 @@ void qmp_cxl_inject_memory_module_event(const char *= path, CxlEventLog log, stl_le_p(&module.corrected_persistent_error_count, corrected_persist_error_count); =20 + if (component_id) { + strncpy((char *)module.component_id, component_id, + sizeof(module.component_id) - 1); + valid_flags |=3D CXL_MMER_VALID_COMPONENT; + if (has_comp_id_pldm && is_comp_id_pldm) { + valid_flags |=3D CXL_MMER_VALID_COMPONENT_ID_FORMAT; + } + } + module.sub_type =3D sub_type; + + stw_le_p(&module.validity_flags, valid_flags); + if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&module)) { cxl_event_irq_assert(ct3d); } diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c index 231dda263f..98292a931c 100644 --- a/hw/mem/cxl_type3_stubs.c +++ b/hw/mem/cxl_type3_stubs.c @@ -78,6 +78,10 @@ void qmp_cxl_inject_memory_module_event(const char *path= , CxlEventLog log, uint32_t dirty_shutdown_count, uint32_t corrected_volatile_error_= count, uint32_t corrected_persist_error_c= ount, + const char *component_id, + bool has_comp_id_pldm, + bool is_comp_id_pldm, + uint8_t sub_type, Error **errp) {} =20 void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t leng= th, diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index a3c5f2ec20..4a7836ad72 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -166,7 +166,7 @@ typedef struct CXLEventDram { =20 /* * Memory Module Event Record - * CXL r3.1 Section 8.2.9.2.1.3: Table 8-47 + * CXL r3.2 Section 8.2.10.2.1.3: Table 8-59 * All fields little endian. */ typedef struct CXLEventMemoryModule { @@ -180,7 +180,10 @@ typedef struct CXLEventMemoryModule { uint32_t dirty_shutdown_count; uint32_t corrected_volatile_error_count; uint32_t corrected_persistent_error_count; - uint8_t reserved[0x3d]; + uint16_t validity_flags; + uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; + uint8_t sub_type; + uint8_t reserved[0x2a]; } QEMU_PACKED CXLEventMemoryModule; =20 /* diff --git a/qapi/cxl.json b/qapi/cxl.json index c2f8b03224..d25a5031be 100644 --- a/qapi/cxl.json +++ b/qapi/cxl.json @@ -240,6 +240,14 @@ # @corrected-persistent-error-count: Total number of correctable # errors in persistent memory # +# @component-id: Device specific component identifier for the event. +# May describe a field replaceable sub-component of the device. +# +# @is-comp-id-pldm: This flag specifies whether the device-specific +# component identifier format follows PLDM. +# +# @sub-type: Device event sub-type. +# # Since: 8.1 ## { 'struct': 'CXLMemModuleEvent', @@ -249,7 +257,9 @@ 'life-used': 'uint8', 'temperature' : 'int16', 'dirty-shutdown-count': 'uint32', 'corrected-volatile-error-count': 'uint32', - 'corrected-persistent-error-count': 'uint32' + 'corrected-persistent-error-count': 'uint32', + '*component-id': 'str', '*is-comp-id-pldm':'bool', + 'sub-type':'uint8' }} =20 ## --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902647; cv=none; d=zohomail.com; s=zohoarc; b=Yi6eII/8zGzRl96eQzotPIv/cjB92E0Swar/jwm86lZHlVN6oDqdSgMQLkkKhZwbB3XlvEwD57NK8g8EcksMlP3MpASoEb49uffggA1B4TSACiiStGSY8j6woEoJkfTSturjT2J99y826RrGna2ay3yANoWNHKQKPNdialvYnIs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902647; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=/9irbaVL7NxzQW3W9A66Gp6A0++m1hls4PRXKvQWa90=; b=iiwMIx4r8wGe41t8HWgyteWIcYshwLi2HxCrllyFAkIBaO+OH2DjnAGNxVStmWJtCuDNJMcJd5G3FhZyM7Mrvd169h5ybbRcuS0Sm2NOY8HESVYOPkP7aqOTk6kyrUMKa3orO7ZY9iwe25g/Qn7G11T+tCMAHwByFeGF/Dvjaug= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902647832898.3159216489477; Mon, 11 Aug 2025 01:57:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKL-00045H-8K; Mon, 11 Aug 2025 04:56:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKG-00044Q-2a for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:17 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vu-Ip for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:14 -0400 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pJT6vR7z6L5ST; Mon, 11 Aug 2025 16:51:05 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id 6C2AD1402F3; Mon, 11 Aug 2025 16:55:52 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:51 +0200 To: , , , , CC: , Subject: [PATCH v6 6/8] hw/cxl/cxl-mailbox-utils: Move declaration of scrub and ECS feature attributes in cmd_features_set_feature() Date: Mon, 11 Aug 2025 09:55:28 +0100 Message-ID: <20250811085530.2263-7-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902669869124100 Content-Type: text/plain; charset="utf-8" From: Shiju Jose Move the declaration of scrub and ECS feature attributes in cmd_features_set_feature() to the local scope where they are used. Signed-off-by: Shiju Jose --- hw/cxl/cxl-mailbox-utils.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index 8f62ea9b54..ce02ae8528 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -1350,10 +1350,6 @@ static CXLRetCode cmd_features_set_feature(const str= uct cxl_cmd *cmd, CXLCCI *cci) { CXLSetFeatureInHeader *hdr =3D (void *)payload_in; - CXLMemPatrolScrubWriteAttrs *ps_write_attrs; - CXLMemPatrolScrubSetFeature *ps_set_feature; - CXLMemECSWriteAttrs *ecs_write_attrs; - CXLMemECSSetFeature *ecs_set_feature; CXLSetFeatureInfo *set_feat_info; uint16_t bytes_to_copy =3D 0; uint8_t data_transfer_flag; @@ -1395,13 +1391,14 @@ static CXLRetCode cmd_features_set_feature(const st= ruct cxl_cmd *cmd, } =20 if (qemu_uuid_is_equal(&hdr->uuid, &patrol_scrub_uuid)) { + CXLMemPatrolScrubSetFeature *ps_set_feature =3D (void *)payload_in; + CXLMemPatrolScrubWriteAttrs *ps_write_attrs =3D + &ps_set_feature->feat_data; + if (hdr->version !=3D CXL_MEMDEV_PS_SET_FEATURE_VERSION) { return CXL_MBOX_UNSUPPORTED; } =20 - ps_set_feature =3D (void *)payload_in; - ps_write_attrs =3D &ps_set_feature->feat_data; - if ((uint32_t)hdr->offset + bytes_to_copy > sizeof(ct3d->patrol_scrub_wr_attrs)) { return CXL_MBOX_INVALID_PAYLOAD_LENGTH; @@ -1422,13 +1419,13 @@ static CXLRetCode cmd_features_set_feature(const st= ruct cxl_cmd *cmd, } } else if (qemu_uuid_is_equal(&hdr->uuid, &ecs_uuid)) { + CXLMemECSSetFeature *ecs_set_feature =3D (void *)payload_in; + CXLMemECSWriteAttrs *ecs_write_attrs =3D ecs_set_feature->feat_dat= a; + if (hdr->version !=3D CXL_ECS_SET_FEATURE_VERSION) { return CXL_MBOX_UNSUPPORTED; } =20 - ecs_set_feature =3D (void *)payload_in; - ecs_write_attrs =3D ecs_set_feature->feat_data; - if ((uint32_t)hdr->offset + bytes_to_copy > sizeof(ct3d->ecs_wr_attrs)) { return CXL_MBOX_INVALID_PAYLOAD_LENGTH; --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902716; cv=none; d=zohomail.com; s=zohoarc; b=NU9ddTC/tVS0KPjLVg2Fqaqm5oKknQDYnlsUil8Xw7H/SlX/VW6IZ+2a75bVTd2M1IsSk+ArHzTz0GXi06qFLAAp5mz98nmCgEl4SROfnPevo+bh0ELfltawgr3k2YZSU3zSwZrdQYftAYIXoFdBnWftx/9S+7wv8vl+uj5QnOM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902716; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=jVX8QJ6SZBuuibhPnXxlxS7CQjg6dqeRMXcXi84pnNk=; b=jMn5SvQvIUJQbbdvei8CrKoBQdIvxamqDWV9pm13hurdroerXuS3oLyKTlbmOhxir4p5K5Rp0Ka2OWW8jlRa2CEjqky7uBqT53FZJxVlI8bm6FPYRoHx95VyYi2KIviOrnH7uMw7wsAU6tO+tBKwnZapU6eM1bk8A8HgAyh6ka8= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902716799148.80755122351286; Mon, 11 Aug 2025 01:58:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKN-000466-9H; Mon, 11 Aug 2025 04:56:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKH-00044U-71 for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:17 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vx-BB for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:16 -0400 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pMp49ttz6M582; Mon, 11 Aug 2025 16:53:58 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id 25CE91404C4; Mon, 11 Aug 2025 16:55:53 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:52 +0200 To: , , , , CC: , Subject: [PATCH v6 7/8] hw/cxl: Add support for Maintenance command and Post Package Repair (PPR) Date: Mon, 11 Aug 2025 09:55:29 +0100 Message-ID: <20250811085530.2263-8-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902718403124100 Content-Type: text/plain; charset="utf-8" From: Davidlohr Bueso This adds initial support for the Maintenance command, specifically the soft and hard PPR operations on a dpa. The implementation allows to be executed at runtime, therefore semantically, data is retained and CXL.mem requests are correctly processed. Keep track of the requests upon a general media or DRAM event. Post Package Repair (PPR) maintenance operations may be supported by CXL devices that implement CXL.mem protocol. A PPR maintenance operation requests the CXL device to perform a repair operation on its media. For example, a CXL device with DRAM components that support PPR features may implement PPR Maintenance operations. DRAM components may support two types of PPR, hard PPR (hPPR), for a permanent row repair, and Soft PPR (sPPR), for a temporary row repair. Soft PPR is much faster than hPPR, but the repair is lost with a power cycle. CXL spec 3.2 section 8.2.10.7.1.2 describes the device's sPPR (soft PPR) maintenance operation and section 8.2.10.7.1.3 describes the device's hPPR (hard PPR) maintenance operation feature. CXL spec 3.2 section 8.2.10.7.2.1 describes the sPPR feature discovery and configuration. CXL spec 3.2 section 8.2.10.7.2.2 describes the hPPR feature discovery and configuration. CXL spec 3.2 section 8.2.10.2.1.4 Table 8-60 describes the Memory Sparing Event Record. Signed-off-by: Davidlohr Bueso Co-developed-by: Shiju Jose Signed-off-by: Shiju Jose --- hw/cxl/cxl-mailbox-utils.c | 240 +++++++++++++++++++++++++++++++++++- hw/mem/cxl_type3.c | 125 +++++++++++++++++++ include/hw/cxl/cxl_device.h | 112 +++++++++++++++++ include/hw/cxl/cxl_events.h | 42 +++++++ 4 files changed, 517 insertions(+), 2 deletions(-) diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index ce02ae8528..254154ceda 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -85,6 +85,8 @@ enum { #define GET_SUPPORTED 0x0 #define GET_FEATURE 0x1 #define SET_FEATURE 0x2 + MAINTENANCE =3D 0x06, + #define PERFORM 0x0 IDENTIFY =3D 0x40, #define MEMORY_DEVICE 0x0 CCLS =3D 0x41, @@ -1110,8 +1112,8 @@ typedef struct CXLSupportedFeatureEntry { #define CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE BIT(0) #define CXL_FEAT_ENTRY_ATTR_FLAG_DEEPEST_RESET_PERSISTENCE_MASK GENMASK(3,= 1) #define CXL_FEAT_ENTRY_ATTR_FLAG_PERSIST_ACROSS_FIRMWARE_UPDATE BIT(4) -#define CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SELECTION BIT(5) -#define CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_SAVED_SELECTION BIT(6) +#define CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL BIT(5) +#define CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_SAVED_SEL BIT(6) =20 /* Supported Feature Entry : set feature effects */ #define CXL_FEAT_ENTRY_SFE_CONFIG_CHANGE_COLD_RESET BIT(0) @@ -1130,6 +1132,8 @@ typedef struct CXLSupportedFeatureEntry { enum CXL_SUPPORTED_FEATURES_LIST { CXL_FEATURE_PATROL_SCRUB =3D 0, CXL_FEATURE_ECS, + CXL_FEATURE_SPPR, + CXL_FEATURE_HPPR, CXL_FEATURE_MAX }; =20 @@ -1171,6 +1175,28 @@ enum CXL_SET_FEATURE_FLAG_DATA_TRANSFER { }; #define CXL_SET_FEAT_DATA_SAVED_ACROSS_RESET BIT(3) =20 +/* CXL r3.2 section 8.2.10.7.2.1: sPPR Feature Discovery and Configuration= */ +static const QemuUUID soft_ppr_uuid =3D { + .data =3D UUID(0x892ba475, 0xfad8, 0x474e, 0x9d, 0x3e, + 0x69, 0x2c, 0x91, 0x75, 0x68, 0xbb) +}; + +typedef struct CXLMemSoftPPRSetFeature { + CXLSetFeatureInHeader hdr; + CXLMemSoftPPRWriteAttrs feat_data; +} QEMU_PACKED QEMU_ALIGNED(16) CXLMemSoftPPRSetFeature; + +/* CXL r3.2 section 8.2.10.7.2.2: hPPR Feature Discovery and Configuration= */ +static const QemuUUID hard_ppr_uuid =3D { + .data =3D UUID(0x80ea4521, 0x786f, 0x4127, 0xaf, 0xb1, + 0xec, 0x74, 0x59, 0xfb, 0x0e, 0x24) +}; + +typedef struct CXLMemHardPPRSetFeature { + CXLSetFeatureInHeader hdr; + CXLMemHardPPRWriteAttrs feat_data; +} QEMU_PACKED QEMU_ALIGNED(16) CXLMemHardPPRSetFeature; + /* CXL r3.1 section 8.2.9.9.11.1: Device Patrol Scrub Control Feature */ static const QemuUUID patrol_scrub_uuid =3D { .data =3D UUID(0x96dad7d6, 0xfde8, 0x482b, 0xa7, 0x33, @@ -1234,6 +1260,38 @@ static CXLRetCode cmd_features_get_supported(const s= truct cxl_cmd *cmd, for (entry =3D 0, index =3D get_feats_in->start_index; entry < req_entries; index++) { switch (index) { + case CXL_FEATURE_SPPR: + /* Fill supported feature entry for soft-PPR */ + get_feats_out->feat_entries[entry++] =3D + (struct CXLSupportedFeatureEntry) { + .uuid =3D soft_ppr_uuid, + .feat_index =3D index, + .get_feat_size =3D sizeof(CXLMemSoftPPRReadAttrs), + .set_feat_size =3D sizeof(CXLMemSoftPPRWriteAttrs), + .attr_flags =3D CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE | + CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL, + .get_feat_version =3D CXL_MEMDEV_SPPR_GET_FEATURE_VERSION, + .set_feat_version =3D CXL_MEMDEV_SPPR_SET_FEATURE_VERSION, + .set_feat_effects =3D CXL_FEAT_ENTRY_SFE_IMMEDIATE_CONFIG_= CHANGE | + CXL_FEAT_ENTRY_SFE_CEL_VALID, + }; + break; + case CXL_FEATURE_HPPR: + /* Fill supported feature entry for hard-PPR */ + get_feats_out->feat_entries[entry++] =3D + (struct CXLSupportedFeatureEntry) { + .uuid =3D hard_ppr_uuid, + .feat_index =3D index, + .get_feat_size =3D sizeof(CXLMemHardPPRReadAttrs), + .set_feat_size =3D sizeof(CXLMemHardPPRWriteAttrs), + .attr_flags =3D CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE | + CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL, + .get_feat_version =3D CXL_MEMDEV_HPPR_GET_FEATURE_VERSION, + .set_feat_version =3D CXL_MEMDEV_HPPR_SET_FEATURE_VERSION, + .set_feat_effects =3D CXL_FEAT_ENTRY_SFE_IMMEDIATE_CONFIG_= CHANGE | + CXL_FEAT_ENTRY_SFE_CEL_VALID, + }; + break; case CXL_FEATURE_PATROL_SCRUB: /* Fill supported feature entry for device patrol scrub contro= l */ get_feats_out->feat_entries[entry++] =3D @@ -1332,6 +1390,26 @@ static CXLRetCode cmd_features_get_feature(const str= uct cxl_cmd *cmd, memcpy(payload_out, (uint8_t *)&ct3d->ecs_attrs + get_feature->offset, bytes_to_copy); + } else if (qemu_uuid_is_equal(&get_feature->uuid, &soft_ppr_uuid)) { + if (get_feature->offset >=3D sizeof(CXLMemSoftPPRReadAttrs)) { + return CXL_MBOX_INVALID_INPUT; + } + bytes_to_copy =3D sizeof(CXLMemSoftPPRReadAttrs) - + get_feature->offset; + bytes_to_copy =3D MIN(bytes_to_copy, get_feature->count); + memcpy(payload_out, + (uint8_t *)&ct3d->soft_ppr_attrs + get_feature->offset, + bytes_to_copy); + } else if (qemu_uuid_is_equal(&get_feature->uuid, &hard_ppr_uuid)) { + if (get_feature->offset >=3D sizeof(CXLMemHardPPRReadAttrs)) { + return CXL_MBOX_INVALID_INPUT; + } + bytes_to_copy =3D sizeof(CXLMemHardPPRReadAttrs) - + get_feature->offset; + bytes_to_copy =3D MIN(bytes_to_copy, get_feature->count); + memcpy(payload_out, + (uint8_t *)&ct3d->hard_ppr_attrs + get_feature->offset, + bytes_to_copy); } else { return CXL_MBOX_UNSUPPORTED; } @@ -1443,6 +1521,44 @@ static CXLRetCode cmd_features_set_feature(const str= uct cxl_cmd *cmd, ct3d->ecs_wr_attrs.fru_attrs[count].ecs_config & 0= x1F; } } + } else if (qemu_uuid_is_equal(&hdr->uuid, &soft_ppr_uuid)) { + CXLMemSoftPPRSetFeature *sppr_set_feature =3D (void *)payload_in; + CXLMemSoftPPRWriteAttrs *sppr_write_attrs =3D + &sppr_set_feature->feat_data; + + if (hdr->version !=3D CXL_MEMDEV_SPPR_SET_FEATURE_VERSION) { + return CXL_MBOX_UNSUPPORTED; + } + + memcpy((uint8_t *)&ct3d->soft_ppr_wr_attrs + hdr->offset, + sppr_write_attrs, bytes_to_copy); + set_feat_info->data_size +=3D bytes_to_copy; + + if (data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FULL_DATA_TRANS= FER || + data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FINISH_DATA_TR= ANSFER) { + ct3d->soft_ppr_attrs.op_mode =3D ct3d->soft_ppr_wr_attrs.op_mo= de; + ct3d->soft_ppr_attrs.sppr_op_mode =3D + ct3d->soft_ppr_wr_attrs.sppr_op_mode; + } + } else if (qemu_uuid_is_equal(&hdr->uuid, &hard_ppr_uuid)) { + CXLMemHardPPRSetFeature *hppr_set_feature =3D (void *)payload_in; + CXLMemHardPPRWriteAttrs *hppr_write_attrs =3D + &hppr_set_feature->feat_data; + + if (hdr->version !=3D CXL_MEMDEV_HPPR_SET_FEATURE_VERSION) { + return CXL_MBOX_UNSUPPORTED; + } + + memcpy((uint8_t *)&ct3d->hard_ppr_wr_attrs + hdr->offset, + hppr_write_attrs, bytes_to_copy); + set_feat_info->data_size +=3D bytes_to_copy; + + if (data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FULL_DATA_TRANS= FER || + data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FINISH_DATA_TR= ANSFER) { + ct3d->hard_ppr_attrs.op_mode =3D ct3d->hard_ppr_wr_attrs.op_mo= de; + ct3d->hard_ppr_attrs.hppr_op_mode =3D + ct3d->hard_ppr_wr_attrs.hppr_op_mode; + } } else { return CXL_MBOX_UNSUPPORTED; } @@ -1455,6 +1571,10 @@ static CXLRetCode cmd_features_set_feature(const str= uct cxl_cmd *cmd, memset(&ct3d->patrol_scrub_wr_attrs, 0, set_feat_info->data_si= ze); } else if (qemu_uuid_is_equal(&hdr->uuid, &ecs_uuid)) { memset(&ct3d->ecs_wr_attrs, 0, set_feat_info->data_size); + } else if (qemu_uuid_is_equal(&hdr->uuid, &soft_ppr_uuid)) { + memset(&ct3d->soft_ppr_wr_attrs, 0, set_feat_info->data_size); + } else if (qemu_uuid_is_equal(&hdr->uuid, &hard_ppr_uuid)) { + memset(&ct3d->hard_ppr_wr_attrs, 0, set_feat_info->data_size); } set_feat_info->data_transfer_flag =3D 0; set_feat_info->data_saved_across_reset =3D false; @@ -1465,6 +1585,116 @@ static CXLRetCode cmd_features_set_feature(const st= ruct cxl_cmd *cmd, return CXL_MBOX_SUCCESS; } =20 +static void cxl_mbox_create_mem_sparing_event_records(CXLType3Dev *ct3d, + uint8_t maint_op_class, uint8_t maint_op_sub_c= lass, + CXLMaintenance *ent) +{ + CXLEventSparing event_rec =3D {}; + + cxl_assign_event_header(&event_rec.hdr, + &sparing_uuid, + (1 << CXL_EVENT_TYPE_INFO), + sizeof(event_rec), + cxl_device_get_timestamp(&ct3d->cxl_dstate), + 1, maint_op_class, 1, maint_op_sub_class, + 0, 0, 0, 0); + if (ent) { + event_rec.flags =3D 0; + event_rec.result =3D 0; + event_rec.res_avail =3D 2; + event_rec.validity_flags =3D ent->validity_flags; + event_rec.channel =3D ent->channel; + event_rec.rank =3D ent->rank; + st24_le_p(event_rec.nibble_mask, ent->nibble_mask); + event_rec.bank_group =3D ent->bank_group; + event_rec.bank =3D ent->bank; + st24_le_p(event_rec.row, ent->row); + event_rec.column =3D ent->column; + event_rec.sub_channel =3D ent->sub_channel; + if (ent->validity_flags & CXL_MSER_VALID_COMP_ID) { + strncpy((char *)event_rec.component_id, (char *)ent->component= _id, + sizeof(event_rec.component_id)); + } + } else { + return; + } + + if (cxl_event_insert(&ct3d->cxl_dstate, + CXL_EVENT_TYPE_INFO, + (CXLEventRecordRaw *)&event_rec)) { + cxl_event_irq_assert(ct3d); + } +} + + +static void cxl_perform_ppr(CXLType3Dev *ct3d, uint64_t dpa) +{ + CXLMaintenance *ent, *next; + + QLIST_FOREACH_SAFE(ent, &ct3d->maint_list, node, next) { + if (dpa =3D=3D ent->dpa) { + /* Produce a Memory Sparing Event Record */ + if (ct3d->soft_ppr_attrs.sppr_op_mode & + CXL_MEMDEV_SPPR_OP_MODE_MEM_SPARING_EV_REC_EN) { + cxl_mbox_create_mem_sparing_event_records(ct3d, + CXL_MEMDEV_MAINT_CLASS_SPARING, + CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARIN= G, + ent); + } + break; + } + } +} + +/* CXL r3.2 section 8.2.10.7.1 - Perform Maintenance (Opcode 0600h) */ +#define MAINTENANCE_PPR_QUERY_RESOURCES BIT(0) + +static CXLRetCode cmd_media_perform_maintenance(const struct cxl_cmd *cmd, + uint8_t *payload_in, size_t len_in, + uint8_t *payload_out, size_t *len_out, + CXLCCI *cci) +{ + struct { + uint8_t class; + uint8_t subclass; + union { + struct { + uint8_t flags; + uint64_t dpa; + uint8_t nibble_mask[3]; + } QEMU_PACKED ppr; + }; + } QEMU_PACKED *maint_in =3D (void *)payload_in; + CXLType3Dev *ct3d =3D CXL_TYPE3(cci->d); + + if (maintenance_running(cci)) { + return CXL_MBOX_BUSY; + } + + switch (maint_in->class) { + case CXL_MEMDEV_MAINT_CLASS_NO_OP: + return CXL_MBOX_SUCCESS; /* nop */ + case CXL_MEMDEV_MAINT_CLASS_PPR: + if (maint_in->ppr.flags & MAINTENANCE_PPR_QUERY_RESOURCES) { + return CXL_MBOX_SUCCESS; + } + + switch (maint_in->subclass) { + case CXL_MEMDEV_MAINT_SUBCLASS_SPPR: + case CXL_MEMDEV_MAINT_SUBCLASS_HPPR: + cxl_perform_ppr(ct3d, ldq_le_p(&maint_in->ppr.dpa)); + return CXL_MBOX_SUCCESS; + default: + return CXL_MBOX_INVALID_INPUT; + } + break; + default: + return CXL_MBOX_INVALID_INPUT; + } + + return CXL_MBOX_SUCCESS; +} + /* CXL r3.1 Section 8.2.9.9.1.1: Identify Memory Device (Opcode 4000h) */ static CXLRetCode cmd_identify_memory_device(const struct cxl_cmd *cmd, uint8_t *payload_in, @@ -3761,6 +3991,12 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = =3D { CXL_MBOX_IMMEDIATE_POLICY_CHANGE | CXL_MBOX_IMMEDIATE_LOG_CHANGE | CXL_MBOX_SECURITY_STATE_CHANGE)}, + [MAINTENANCE][PERFORM] =3D { "MAINTENANCE_PERFORM", + cmd_media_perform_maintenance, ~0, + CXL_MBOX_IMMEDIATE_CONFIG_CHANGE | + CXL_MBOX_IMMEDIATE_DATA_CHANGE | + CXL_MBOX_IMMEDIATE_LOG_CHANGE | + CXL_MBOX_BACKGROUND_OPERATION }, [IDENTIFY][MEMORY_DEVICE] =3D { "IDENTIFY_MEMORY_DEVICE", cmd_identify_memory_device, 0, 0 }, [CCLS][GET_PARTITION_INFO] =3D { "CCLS_GET_PARTITION_INFO", diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index c0578af972..6036c610e6 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -964,6 +964,32 @@ static void ct3_realize(PCIDevice *pci_dev, Error **er= rp) ct3d->ecs_attrs.fru_attrs[count].ecs_flags =3D 0; } =20 + /* Set default values for soft-PPR attributes */ + ct3d->soft_ppr_attrs =3D (CXLMemSoftPPRReadAttrs) { + .max_maint_latency =3D 0x5, /* 100 ms */ + .op_caps =3D 0, /* require host involvement */ + .op_mode =3D 0, + .maint_op_class =3D CXL_MEMDEV_MAINT_CLASS_PPR, + .maint_op_subclass =3D CXL_MEMDEV_MAINT_SUBCLASS_SPPR, + .sppr_flags =3D CXL_MEMDEV_SPPR_DPA_SUPPORT_FLAG | + CXL_MEMDEV_SPPR_MEM_SPARING_EV_REC_CAP_FLAG, + .restriction_flags =3D 0, + .sppr_op_mode =3D CXL_MEMDEV_SPPR_OP_MODE_MEM_SPARING_EV_REC_EN + }; + + /* Set default value for hard-PPR attributes */ + ct3d->hard_ppr_attrs =3D (CXLMemHardPPRReadAttrs) { + .max_maint_latency =3D 0x5, /* 100 ms */ + .op_caps =3D 0, /* require host involvement */ + .op_mode =3D 0, + .maint_op_class =3D CXL_MEMDEV_MAINT_CLASS_PPR, + .maint_op_subclass =3D CXL_MEMDEV_MAINT_SUBCLASS_HPPR, + .hppr_flags =3D CXL_MEMDEV_HPPR_DPA_SUPPORT_FLAG | + CXL_MEMDEV_HPPR_MEM_SPARING_EV_REC_CAP_FLAG, + .restriction_flags =3D 0, + .hppr_op_mode =3D CXL_MEMDEV_HPPR_OP_MODE_MEM_SPARING_EV_REC_EN + }; + return; =20 err_release_cdat: @@ -1667,6 +1693,75 @@ static int ct3d_qmp_cxl_event_log_enc(CxlEventLog lo= g) return -EINVAL; } } + +static void cxl_maintenance_insert(CXLType3Dev *ct3d, uint64_t dpa, + bool has_channel, uint8_t channel, + bool has_rank, uint8_t rank, + bool has_nibble_mask, uint32_t nibble_m= ask, + bool has_bank_group, uint8_t bank_group, + bool has_bank, uint8_t bank, + bool has_row, uint32_t row, + bool has_column, uint16_t column, + const char *component_id, + bool has_comp_id_pldm, bool is_comp_id_= pldm, + bool has_sub_channel, uint8_t sub_chann= el) +{ + CXLMaintenance *ent, *m; + + QLIST_FOREACH(ent, &ct3d->maint_list, node) { + if (dpa =3D=3D ent->dpa) { + return; + } + } + m =3D g_new0(CXLMaintenance, 1); + memset(m, 0, sizeof(*m)); + m->dpa =3D dpa; + m->validity_flags =3D 0; + + if (has_channel) { + m->channel =3D channel; + m->validity_flags |=3D CXL_MSER_VALID_CHANNEL; + } + if (has_rank) { + m->rank =3D rank; + m->validity_flags |=3D CXL_MSER_VALID_RANK; + } + if (has_nibble_mask) { + m->nibble_mask =3D nibble_mask; + m->validity_flags |=3D CXL_MSER_VALID_NIB_MASK; + } + if (has_bank_group) { + m->bank_group =3D bank_group; + m->validity_flags |=3D CXL_MSER_VALID_BANK_GROUP; + } + if (has_bank) { + m->bank =3D bank; + m->validity_flags |=3D CXL_MSER_VALID_BANK; + } + if (has_row) { + m->row =3D row; + m->validity_flags |=3D CXL_MSER_VALID_ROW; + } + if (has_column) { + m->column =3D column; + m->validity_flags |=3D CXL_MSER_VALID_COLUMN; + } + if (has_sub_channel) { + m->sub_channel =3D sub_channel; + m->validity_flags |=3D CXL_MSER_VALID_SUB_CHANNEL; + } + if (component_id) { + strncpy((char *)m->component_id, component_id, + sizeof(m->component_id) - 1); + m->validity_flags |=3D CXL_MSER_VALID_COMP_ID; + if (has_comp_id_pldm && is_comp_id_pldm) { + m->validity_flags |=3D CXL_MSER_VALID_COMP_ID_FORMAT; + } + } + + QLIST_INSERT_HEAD(&ct3d->maint_list, m, node); +} + /* Component ID is device specific. Define this as a string. */ void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log, uint32_t flags, bool has_maint_op_= class, @@ -1715,6 +1810,11 @@ void qmp_cxl_inject_general_media_event(const char *= path, CxlEventLog log, error_setg(errp, "Unhandled error log type"); return; } + if (rc =3D=3D CXL_EVENT_TYPE_INFO && + (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED)) { + error_setg(errp, "Informational event cannot require maintenance"); + return; + } enc_log =3D rc; =20 memset(&gem, 0, sizeof(gem)); @@ -1773,6 +1873,15 @@ void qmp_cxl_inject_general_media_event(const char *= path, CxlEventLog log, if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&gem)) { cxl_event_irq_assert(ct3d); } + + if (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED) { + cxl_maintenance_insert(ct3d, dpa, has_channel, channel, + has_rank, rank, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, component_id, + has_comp_id_pldm, is_comp_id_pldm, + 0, 0); + } } =20 #define CXL_DRAM_VALID_CHANNEL BIT(0) @@ -1842,6 +1951,11 @@ void qmp_cxl_inject_dram_event(const char *path, Cxl= EventLog log, error_setg(errp, "Unhandled error log type"); return; } + if (rc =3D=3D CXL_EVENT_TYPE_INFO && + (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED)) { + error_setg(errp, "Informational event cannot require maintenance"); + return; + } enc_log =3D rc; =20 memset(&dram, 0, sizeof(dram)); @@ -1935,6 +2049,17 @@ void qmp_cxl_inject_dram_event(const char *path, Cxl= EventLog log, if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&dram)) { cxl_event_irq_assert(ct3d); } + + if (flags & CXL_EVENT_REC_FLAGS_MAINT_NEEDED) { + cxl_maintenance_insert(ct3d, dpa, has_channel, channel, + has_rank, rank, + has_nibble_mask, nibble_mask, + has_bank_group, bank_group, + has_bank, bank, has_row, row, + has_column, column, component_id, + has_comp_id_pldm, is_comp_id_pldm, + has_sub_channel, sub_channel); + } } =20 #define CXL_MMER_VALID_COMPONENT BIT(0) diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index b77b6b2499..959049aa46 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -430,6 +430,12 @@ static inline bool cxl_dev_media_disabled(CXLDeviceSta= te *cxl_dstate) uint64_t dev_status_reg =3D cxl_dstate->mbox_reg_state64[R_CXL_MEM_DEV= _STS]; return FIELD_EX64(dev_status_reg, CXL_MEM_DEV_STS, MEDIA_STATUS) =3D= =3D 0x3; } + +static inline bool maintenance_running(CXLCCI *cci) +{ + return cci->bg.runtime && cci->bg.opcode =3D=3D 0x0600; +} + static inline bool scan_media_running(CXLCCI *cci) { return !!cci->bg.runtime && cci->bg.opcode =3D=3D 0x4304; @@ -443,6 +449,23 @@ typedef struct CXLError { =20 typedef QTAILQ_HEAD(, CXLError) CXLErrorList; =20 +typedef struct CXLMaintenance { + uint64_t dpa; + uint16_t validity_flags; + uint8_t channel; + uint8_t rank; + uint32_t nibble_mask; + uint8_t bank_group; + uint8_t bank; + uint32_t row; + uint16_t column; + uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; + uint8_t sub_channel; + QLIST_ENTRY(CXLMaintenance) node; +} CXLMaintenance; + +typedef QLIST_HEAD(, CXLMaintenance) CXLMaintenanceList; + typedef struct CXLPoison { uint64_t start, length; uint8_t type; @@ -455,6 +478,87 @@ typedef struct CXLPoison { typedef QLIST_HEAD(, CXLPoison) CXLPoisonList; #define CXL_POISON_LIST_LIMIT 256 =20 +/* CXL memory maintenance operation */ +/* + * CXL r3.2 section 8.2.10.7.2, Table 8-125: Mainteance Operation: + * Classes, Subclasses, and Feature UUIDs + */ +#define CXL_MEMDEV_MAINT_CLASS_NO_OP 0x0 +#define CXL_MEMDEV_MAINT_CLASS_PPR 0x1 +#define CXL_MEMDEV_MAINT_CLASS_SPARING 0x2 +#define CXL_MEMDEV_MAINT_CLASS_DEV_BUILT_IN_TEST 0x3 + +#define CXL_MEMDEV_MAINT_SUBCLASS_SPPR 0x0 +#define CXL_MEMDEV_MAINT_SUBCLASS_HPPR 0x1 + +#define CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING 0x0 +#define CXL_MEMDEV_MAINT_SUBCLASS_ROW_SPARING 0x1 +#define CXL_MEMDEV_MAINT_SUBCLASS_BANK_SPARING 0x2 +#define CXL_MEMDEV_MAINT_SUBCLASS_RANK_SPARING 0x3 + +/* CXL memory Post Package Repair control attributes */ +/* + * CXL r3.2 section 8.2.10.7.2.1, Table 8-128 and 8-129: + * sPPR Feature Readable/Writable Attributes + */ +typedef struct CXLMemSoftPPRReadAttrs { + uint8_t max_maint_latency; + uint16_t op_caps; + uint16_t op_mode; + uint8_t maint_op_class; + uint8_t maint_op_subclass; + uint8_t rsvd[9]; + uint8_t sppr_flags; + uint16_t restriction_flags; + uint8_t sppr_op_mode; +} QEMU_PACKED CXLMemSoftPPRReadAttrs; + +typedef struct CXLMemSoftPPRWriteAttrs { + uint16_t op_mode; + uint8_t sppr_op_mode; +} QEMU_PACKED CXLMemSoftPPRWriteAttrs; + +#define CXL_MEMDEV_SPPR_GET_FEATURE_VERSION 0x03 +#define CXL_MEMDEV_SPPR_SET_FEATURE_VERSION 0x03 +#define CXL_MEMDEV_SPPR_DPA_SUPPORT_FLAG BIT(0) +#define CXL_MEMDEV_SPPR_NIBBLE_SUPPORT_FLAG BIT(1) +#define CXL_MEMDEV_SPPR_MEM_SPARING_EV_REC_CAP_FLAG BIT(2) +#define CXL_MEMDEV_SPPR_DEV_INITIATED_AT_BOOT_CAP_FLAG BIT(3) + +#define CXL_MEMDEV_SPPR_OP_MODE_MEM_SPARING_EV_REC_EN BIT(0) +#define CXL_MEMDEV_SPPR_OP_MODE_DEV_INITIATED_AT_BOOT BIT(1) + +/* + * CXL r3.2 section 8.2.10.7.2.2, Table 8-131 and 8-132: + * hPPR Feature Readable/Writable Attributes + */ +typedef struct CXLMemHardPPRReadAttrs { + uint8_t max_maint_latency; + uint16_t op_caps; + uint16_t op_mode; + uint8_t maint_op_class; + uint8_t maint_op_subclass; + uint8_t rsvd[9]; + uint8_t hppr_flags; + uint16_t restriction_flags; + uint8_t hppr_op_mode; +} QEMU_PACKED CXLMemHardPPRReadAttrs; + +typedef struct CXLMemHardPPRWriteAttrs { + uint16_t op_mode; + uint8_t hppr_op_mode; +} QEMU_PACKED CXLMemHardPPRWriteAttrs; + +#define CXL_MEMDEV_HPPR_GET_FEATURE_VERSION 0x03 +#define CXL_MEMDEV_HPPR_SET_FEATURE_VERSION 0x03 +#define CXL_MEMDEV_HPPR_DPA_SUPPORT_FLAG BIT(0) +#define CXL_MEMDEV_HPPR_NIBBLE_SUPPORT_FLAG BIT(1) +#define CXL_MEMDEV_HPPR_MEM_SPARING_EV_REC_CAP_FLAG BIT(2) +#define CXL_MEMDEV_HPPR_DEV_INITIATED_AT_BOOT_CAP_FLAG BIT(3) + +#define CXL_MEMDEV_HPPR_OP_MODE_MEM_SPARING_EV_REC_EN BIT(0) +#define CXL_MEMDEV_HPPR_OP_MODE_DEV_INITIATED_AT_BOOT BIT(1) + /* CXL memory device patrol scrub control attributes */ typedef struct CXLMemPatrolScrubReadAttrs { uint8_t scrub_cycle_cap; @@ -605,6 +709,9 @@ struct CXLType3Dev { /* Error injection */ CXLErrorList error_list; =20 + /* Keep track of maintenance requests */ + CXLMaintenanceList maint_list; + /* Poison Injection - cache */ CXLPoisonList poison_list; unsigned int poison_list_cnt; @@ -617,6 +724,11 @@ struct CXLType3Dev { =20 CXLSetFeatureInfo set_feat_info; =20 + /* PPR control attributes */ + CXLMemSoftPPRReadAttrs soft_ppr_attrs; + CXLMemSoftPPRWriteAttrs soft_ppr_wr_attrs; + CXLMemHardPPRReadAttrs hard_ppr_attrs; + CXLMemHardPPRWriteAttrs hard_ppr_wr_attrs; /* Patrol scrub control attributes */ CXLMemPatrolScrubReadAttrs patrol_scrub_attrs; CXLMemPatrolScrubWriteAttrs patrol_scrub_wr_attrs; diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 4a7836ad72..3052bc9f18 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -219,4 +219,46 @@ typedef enum CXLDCEventType { DC_EVENT_CAPACITY_RELEASED =3D 0x5, } CXLDCEventType; =20 +/* + * CXL r3.2 section Table 8-60: Memory Sparing Event Record + * All fields little endian. + */ +#define CXL_MSER_VALID_CHANNEL BIT(0) +#define CXL_MSER_VALID_RANK BIT(1) +#define CXL_MSER_VALID_NIB_MASK BIT(2) +#define CXL_MSER_VALID_BANK_GROUP BIT(3) +#define CXL_MSER_VALID_BANK BIT(4) +#define CXL_MSER_VALID_ROW BIT(5) +#define CXL_MSER_VALID_COLUMN BIT(6) +#define CXL_MSER_VALID_COMP_ID BIT(7) +#define CXL_MSER_VALID_COMP_ID_FORMAT BIT(8) +#define CXL_MSER_VALID_SUB_CHANNEL BIT(9) + +typedef struct CXLEventSparing { + CXLEventRecordHdr hdr; + uint8_t maint_op_class; + uint8_t maint_op_subclass; + uint8_t flags; + uint8_t result; + uint16_t validity_flags; + uint8_t reserved1[6]; + uint16_t res_avail; + uint8_t channel; + uint8_t rank; + uint8_t nibble_mask[3]; + uint8_t bank_group; + uint8_t bank; + uint8_t row[3]; + uint16_t column; + uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE]; + uint8_t sub_channel; + uint8_t reserved2[0x25]; +} QEMU_PACKED CXLEventSparing; + +/* CXL r3.2 Table 8-60: Memory Sparing Event Record */ +static const QemuUUID sparing_uuid =3D { + .data =3D UUID(0xe71f3a40, 0x2d29, 0x4092, 0x8a, 0x39, + 0x4d, 0x1c, 0x96, 0x6c, 0x7c, 0x65), +}; + #endif /* CXL_EVENTS_H */ --=20 2.43.0 From nobody Wed Sep 10 19:17:27 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1754902685; cv=none; d=zohomail.com; s=zohoarc; b=mK2LgkT3qdy6D6iJdX5Xh38ip9buS9UG8FRGecCrletVhZMPRt5ipJ1+RPc+03rp6bcFRIPqbk8X25P5LsxRRHKCXBVSnR19elRdIa9X8Yf1NOlVItzLUWlRl3sULOJhysExL4crXqoltVsCEpypAmFGqJKBbDkS/vv7RXJWcTI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754902685; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=4GVyCx5MC0C2J5CeANCyro3tJ3N2P71Rzj3S5ixy7qQ=; b=I4qr+4HWRgF1vkyEKs3k0AC/9mTS23ZrBynQLP07BU9Lo8VBt3oDZlGGXXX4Xm6CEqiSbKQcSP6+ct86D7a7AqJrx76M2DD0DeMlG0MO8Y9mlgqRdqAIQiGsXE0qakQquIuKEv8L/ZAckEuMGZMUFONBEvo7RcfiVgyoEN2n61A= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754902685399913.3128344582326; Mon, 11 Aug 2025 01:58:05 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ulOKS-00047F-0Y; Mon, 11 Aug 2025 04:56:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOKG-00044P-1a for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:17 -0400 Received: from [185.176.79.56] (helo=frasgout.his.huawei.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ulOK8-0003Vz-Am for qemu-devel@nongnu.org; Mon, 11 Aug 2025 04:56:15 -0400 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4c0pM40Fdhz6L5HN; Mon, 11 Aug 2025 16:53:20 +0800 (CST) Received: from frapeml500007.china.huawei.com (unknown [7.182.85.172]) by mail.maildlp.com (Postfix) with ESMTPS id E75091402F3; Mon, 11 Aug 2025 16:55:53 +0800 (CST) Received: from P_UKIT01-A7bmah.china.huawei.com (10.48.146.213) by frapeml500007.china.huawei.com (7.182.85.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Mon, 11 Aug 2025 10:55:53 +0200 To: , , , , CC: , Subject: [PATCH v6 8/8] hw/cxl: Add emulation for memory sparing control feature Date: Mon, 11 Aug 2025 09:55:30 +0100 Message-ID: <20250811085530.2263-9-shiju.jose@huawei.com> X-Mailer: git-send-email 2.43.0.windows.1 In-Reply-To: <20250811085530.2263-1-shiju.jose@huawei.com> References: <20250811085530.2263-1-shiju.jose@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.48.146.213] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To frapeml500007.china.huawei.com (7.182.85.172) X-Host-Lookup-Failed: Reverse DNS lookup failed for 185.176.79.56 (deferred) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=shiju.jose@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: From: shiju.jose--- via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1754902687981124100 Content-Type: text/plain; charset="utf-8" From: Shiju Jose Memory sparing is defined as a repair function that replaces a portion of memory with a portion of functional memory at that same DPA. The subclasses for this operation vary in terms of the scope of the sparing being performed. The Cacheline sparing subclass refers to a sparing action that can replace a full cacheline. Row sparing is provided as an alternative to PPR sparing functions and its scope is that of a single DDR row. Bank sparing allows an entire bank to be replaced. Rank sparing is defined as an operation in which an entire DDR rank is replaced. Memory sparing maintenance operations may be supported by CXL devices that implement CXL.mem protocol. A sparing maintenance operation requests the CXL device to perform a repair operation on its media. For example, a CXL device with DRAM components that support memory sparing features may implement sparing Maintenance operations. The host may issue a query command by setting Query Resources flag in the Input Payload (CXL Spec 3.2 Table 8-120) to determine availability of sparing resources for a given address. In response to a query request, the device shall report the resource availability by producing the Memory Sparing Event Record (CXL Spec 3.2 Table 8-60) in which the Channel, Rank, Nibble Mask, Bank Group, Bank, Row, Column, Sub-Channel fields are a copy of the values specified in the request. During the execution of a sparing maintenance operation, a CXL memory device: - May or may not retain data - May or may not be able to process CXL.mem requests correctly. These CXL memory device capabilities are specified by restriction flags in the memory sparing feature readable attributes. When a CXL device identifies error on a memory component, the device may inform the host about the need for a memory sparing maintenance operation by using DRAM event record, where the 'maintenance needed' flag may set. The event record contains some of the DPA, Channel, Rank, Nibble Mask, Bank Group, Bank, Row, Column, Sub-Channel fields that should be repaired. The userspace tool requests for maintenance operation if the 'maintenance needed' flag set in the CXL DRAM error record. CXL spec 3.2 section 8.2.10.7.2.3 describes the memory sparing feature discovery and configuration. CXL spec 3.2 section 8.2.10.7.1.4 describes the device's memory sparing maintenance operation feature. Add emulation for CXL memory device memory sparing control feature and memory sparing maintenance operation command. Signed-off-by: Shiju Jose --- hw/cxl/cxl-mailbox-utils.c | 317 +++++++++++++++++++++++++++++++++++- hw/mem/cxl_type3.c | 44 +++++ include/hw/cxl/cxl_device.h | 33 ++++ include/hw/cxl/cxl_events.h | 5 + 4 files changed, 395 insertions(+), 4 deletions(-) diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index 254154ceda..a3ab3b48f2 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -1134,6 +1134,10 @@ enum CXL_SUPPORTED_FEATURES_LIST { CXL_FEATURE_ECS, CXL_FEATURE_SPPR, CXL_FEATURE_HPPR, + CXL_FEATURE_CACHELINE_SPARING, + CXL_FEATURE_ROW_SPARING, + CXL_FEATURE_BANK_SPARING, + CXL_FEATURE_RANK_SPARING, CXL_FEATURE_MAX }; =20 @@ -1222,6 +1226,35 @@ typedef struct CXLMemECSSetFeature { CXLMemECSWriteAttrs feat_data[]; } QEMU_PACKED QEMU_ALIGNED(16) CXLMemECSSetFeature; =20 +/* + * CXL r3.2 section 8.2.10.7.2.3: + * Memory Sparing Features Discovery and Configuration + */ +static const QemuUUID cacheline_sparing_uuid =3D { + .data =3D UUID(0x96C33386, 0x91dd, 0x44c7, 0x9e, 0xcb, + 0xfd, 0xaf, 0x65, 0x03, 0xba, 0xc4) +}; + +static const QemuUUID row_sparing_uuid =3D { + .data =3D UUID(0x450ebf67, 0xb135, 0x4f97, 0xa4, 0x98, + 0xc2, 0xd5, 0x7f, 0x27, 0x9b, 0xed) +}; + +static const QemuUUID bank_sparing_uuid =3D { + .data =3D UUID(0x78b79636, 0x90ac, 0x4b64, 0xa4, 0xef, + 0xfa, 0xac, 0x5d, 0x18, 0xa8, 0x63) +}; + +static const QemuUUID rank_sparing_uuid =3D { + .data =3D UUID(0x34dbaff5, 0x0552, 0x4281, 0x8f, 0x76, + 0xda, 0x0b, 0x5e, 0x7a, 0x76, 0xa7) +}; + +typedef struct CXLMemSparingSetFeature { + CXLSetFeatureInHeader hdr; + CXLMemSparingWriteAttrs feat_data; +} QEMU_PACKED QEMU_ALIGNED(16) CXLMemSparingSetFeature; + /* CXL r3.1 section 8.2.9.6.1: Get Supported Features (Opcode 0500h) */ static CXLRetCode cmd_features_get_supported(const struct cxl_cmd *cmd, uint8_t *payload_in, @@ -1322,6 +1355,70 @@ static CXLRetCode cmd_features_get_supported(const s= truct cxl_cmd *cmd, CXL_FEAT_ENTRY_SFE_CEL_VALID, }; break; + case CXL_FEATURE_CACHELINE_SPARING: + /* Fill supported feature entry for Cacheline Memory Sparing */ + get_feats_out->feat_entries[entry++] =3D + (struct CXLSupportedFeatureEntry) { + .uuid =3D cacheline_sparing_uuid, + .feat_index =3D index, + .get_feat_size =3D sizeof(CXLMemSparingReadAttrs), + .set_feat_size =3D sizeof(CXLMemSparingWriteAttrs), + .attr_flags =3D CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE | + CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL, + .get_feat_version =3D CXL_MEMDEV_SPARING_GET_FEATURE_VERSI= ON, + .set_feat_version =3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSI= ON, + .set_feat_effects =3D CXL_FEAT_ENTRY_SFE_IMMEDIATE_CONFIG_= CHANGE | + CXL_FEAT_ENTRY_SFE_CEL_VALID, + }; + break; + case CXL_FEATURE_ROW_SPARING: + /* Fill supported feature entry for Row Memory Sparing */ + get_feats_out->feat_entries[entry++] =3D + (struct CXLSupportedFeatureEntry) { + .uuid =3D row_sparing_uuid, + .feat_index =3D index, + .get_feat_size =3D sizeof(CXLMemSparingReadAttrs), + .set_feat_size =3D sizeof(CXLMemSparingWriteAttrs), + .attr_flags =3D CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE | + CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL, + .get_feat_version =3D CXL_MEMDEV_SPARING_GET_FEATURE_VERSI= ON, + .set_feat_version =3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSI= ON, + .set_feat_effects =3D CXL_FEAT_ENTRY_SFE_IMMEDIATE_CONFIG_= CHANGE | + CXL_FEAT_ENTRY_SFE_CEL_VALID, + }; + break; + case CXL_FEATURE_BANK_SPARING: + /* Fill supported feature entry for Bank Memory Sparing */ + get_feats_out->feat_entries[entry++] =3D + (struct CXLSupportedFeatureEntry) { + .uuid =3D bank_sparing_uuid, + .feat_index =3D index, + .get_feat_size =3D sizeof(CXLMemSparingReadAttrs), + .set_feat_size =3D sizeof(CXLMemSparingWriteAttrs), + .attr_flags =3D CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE | + CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL, + .get_feat_version =3D CXL_MEMDEV_SPARING_GET_FEATURE_VERSI= ON, + .set_feat_version =3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSI= ON, + .set_feat_effects =3D CXL_FEAT_ENTRY_SFE_IMMEDIATE_CONFIG_= CHANGE | + CXL_FEAT_ENTRY_SFE_CEL_VALID, + }; + break; + case CXL_FEATURE_RANK_SPARING: + /* Fill supported feature entry for Rank Memory Sparing */ + get_feats_out->feat_entries[entry++] =3D + (struct CXLSupportedFeatureEntry) { + .uuid =3D rank_sparing_uuid, + .feat_index =3D index, + .get_feat_size =3D sizeof(CXLMemSparingReadAttrs), + .set_feat_size =3D sizeof(CXLMemSparingWriteAttrs), + .attr_flags =3D CXL_FEAT_ENTRY_ATTR_FLAG_CHANGABLE | + CXL_FEAT_ENTRY_ATTR_FLAG_SUPPORT_DEFAULT_SEL, + .get_feat_version =3D CXL_MEMDEV_SPARING_GET_FEATURE_VERSI= ON, + .set_feat_version =3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSI= ON, + .set_feat_effects =3D CXL_FEAT_ENTRY_SFE_IMMEDIATE_CONFIG_= CHANGE | + CXL_FEAT_ENTRY_SFE_CEL_VALID, + }; + break; default: __builtin_unreachable(); } @@ -1410,6 +1507,47 @@ static CXLRetCode cmd_features_get_feature(const str= uct cxl_cmd *cmd, memcpy(payload_out, (uint8_t *)&ct3d->hard_ppr_attrs + get_feature->offset, bytes_to_copy); + } else if (qemu_uuid_is_equal(&get_feature->uuid, + &cacheline_sparing_uuid)) { + if (get_feature->offset >=3D sizeof(CXLMemSparingReadAttrs)) { + return CXL_MBOX_INVALID_INPUT; + } + bytes_to_copy =3D sizeof(CXLMemSparingReadAttrs) - + get_feature->offset; + bytes_to_copy =3D MIN(bytes_to_copy, get_feature->count); + memcpy(payload_out, + (uint8_t *)&ct3d->cacheline_sparing_attrs + get_feature->of= fset, + bytes_to_copy); + } else if (qemu_uuid_is_equal(&get_feature->uuid, &row_sparing_uuid)) { + if (get_feature->offset >=3D sizeof(CXLMemSparingReadAttrs)) { + return CXL_MBOX_INVALID_INPUT; + } + bytes_to_copy =3D sizeof(CXLMemSparingReadAttrs) - + get_feature->offset; + bytes_to_copy =3D MIN(bytes_to_copy, get_feature->count); + memcpy(payload_out, + (uint8_t *)&ct3d->row_sparing_attrs + get_feature->offset, + bytes_to_copy); + } else if (qemu_uuid_is_equal(&get_feature->uuid, &bank_sparing_uuid))= { + if (get_feature->offset >=3D sizeof(CXLMemSparingReadAttrs)) { + return CXL_MBOX_INVALID_INPUT; + } + bytes_to_copy =3D sizeof(CXLMemSparingReadAttrs) - + get_feature->offset; + bytes_to_copy =3D MIN(bytes_to_copy, get_feature->count); + memcpy(payload_out, + (uint8_t *)&ct3d->bank_sparing_attrs + get_feature->offset, + bytes_to_copy); + } else if (qemu_uuid_is_equal(&get_feature->uuid, &rank_sparing_uuid))= { + if (get_feature->offset >=3D sizeof(CXLMemSparingReadAttrs)) { + return CXL_MBOX_INVALID_INPUT; + } + bytes_to_copy =3D sizeof(CXLMemSparingReadAttrs) - + get_feature->offset; + bytes_to_copy =3D MIN(bytes_to_copy, get_feature->count); + memcpy(payload_out, + (uint8_t *)&ct3d->rank_sparing_attrs + get_feature->offset, + bytes_to_copy); } else { return CXL_MBOX_UNSUPPORTED; } @@ -1559,6 +1697,78 @@ static CXLRetCode cmd_features_set_feature(const str= uct cxl_cmd *cmd, ct3d->hard_ppr_attrs.hppr_op_mode =3D ct3d->hard_ppr_wr_attrs.hppr_op_mode; } + } else if (qemu_uuid_is_equal(&hdr->uuid, &cacheline_sparing_uuid)) { + CXLMemSparingSetFeature *mem_sparing_set_feature =3D (void *)paylo= ad_in; + CXLMemSparingWriteAttrs *mem_sparing_write_attrs =3D + &mem_sparing_set_feature->feat_data; + + if (hdr->version !=3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSION) { + return CXL_MBOX_UNSUPPORTED; + } + + memcpy((uint8_t *)&ct3d->cacheline_sparing_wr_attrs + hdr->offset, + mem_sparing_write_attrs, bytes_to_copy); + set_feat_info->data_size +=3D bytes_to_copy; + + if (data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FULL_DATA_TRANS= FER || + data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FINISH_DATA_TRA= NSFER) { + ct3d->cacheline_sparing_attrs.op_mode =3D + ct3d->cacheline_sparing_wr_attrs.op_mo= de; + } + } else if (qemu_uuid_is_equal(&hdr->uuid, &row_sparing_uuid)) { + CXLMemSparingSetFeature *mem_sparing_set_feature =3D (void *)paylo= ad_in; + CXLMemSparingWriteAttrs *mem_sparing_write_attrs =3D + &mem_sparing_set_feature->feat_data; + + if (hdr->version !=3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSION) { + return CXL_MBOX_UNSUPPORTED; + } + + memcpy((uint8_t *)&ct3d->row_sparing_wr_attrs + hdr->offset, + mem_sparing_write_attrs, bytes_to_copy); + set_feat_info->data_size +=3D bytes_to_copy; + + if (data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FULL_DATA_TRANS= FER || + data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FINISH_DATA_TRA= NSFER) { + ct3d->row_sparing_attrs.op_mode =3D + ct3d->row_sparing_wr_attrs.op_mode; + } + } else if (qemu_uuid_is_equal(&hdr->uuid, &bank_sparing_uuid)) { + CXLMemSparingSetFeature *mem_sparing_set_feature =3D (void *)paylo= ad_in; + CXLMemSparingWriteAttrs *mem_sparing_write_attrs =3D + &mem_sparing_set_feature->feat_data; + + if (hdr->version !=3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSION) { + return CXL_MBOX_UNSUPPORTED; + } + + memcpy((uint8_t *)&ct3d->bank_sparing_wr_attrs + hdr->offset, + mem_sparing_write_attrs, bytes_to_copy); + set_feat_info->data_size +=3D bytes_to_copy; + + if (data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FULL_DATA_TRANS= FER || + data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FINISH_DATA_TRA= NSFER) { + ct3d->bank_sparing_attrs.op_mode =3D + ct3d->bank_sparing_wr_attrs.op_mode; + } + } else if (qemu_uuid_is_equal(&hdr->uuid, &rank_sparing_uuid)) { + CXLMemSparingSetFeature *mem_sparing_set_feature =3D (void *)paylo= ad_in; + CXLMemSparingWriteAttrs *mem_sparing_write_attrs =3D + &mem_sparing_set_feature->feat_data; + + if (hdr->version !=3D CXL_MEMDEV_SPARING_SET_FEATURE_VERSION) { + return CXL_MBOX_UNSUPPORTED; + } + + memcpy((uint8_t *)&ct3d->rank_sparing_wr_attrs + hdr->offset, + mem_sparing_write_attrs, bytes_to_copy); + set_feat_info->data_size +=3D bytes_to_copy; + + if (data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FULL_DATA_TRANS= FER || + data_transfer_flag =3D=3D CXL_SET_FEATURE_FLAG_FINISH_DATA_TRA= NSFER) { + ct3d->rank_sparing_attrs.op_mode =3D + ct3d->rank_sparing_wr_attrs.op_mode; + } } else { return CXL_MBOX_UNSUPPORTED; } @@ -1575,6 +1785,15 @@ static CXLRetCode cmd_features_set_feature(const str= uct cxl_cmd *cmd, memset(&ct3d->soft_ppr_wr_attrs, 0, set_feat_info->data_size); } else if (qemu_uuid_is_equal(&hdr->uuid, &hard_ppr_uuid)) { memset(&ct3d->hard_ppr_wr_attrs, 0, set_feat_info->data_size); + } else if (qemu_uuid_is_equal(&hdr->uuid, &cacheline_sparing_uuid)= ) { + memset(&ct3d->cacheline_sparing_wr_attrs, 0, + set_feat_info->data_size); + } else if (qemu_uuid_is_equal(&hdr->uuid, &row_sparing_uuid)) { + memset(&ct3d->row_sparing_wr_attrs, 0, set_feat_info->data_siz= e); + } else if (qemu_uuid_is_equal(&hdr->uuid, &bank_sparing_uuid)) { + memset(&ct3d->bank_sparing_wr_attrs, 0, set_feat_info->data_si= ze); + } else if (qemu_uuid_is_equal(&hdr->uuid, &rank_sparing_uuid)) { + memset(&ct3d->rank_sparing_wr_attrs, 0, set_feat_info->data_si= ze); } set_feat_info->data_transfer_flag =3D 0; set_feat_info->data_saved_across_reset =3D false; @@ -1585,9 +1804,27 @@ static CXLRetCode cmd_features_set_feature(const str= uct cxl_cmd *cmd, return CXL_MBOX_SUCCESS; } =20 -static void cxl_mbox_create_mem_sparing_event_records(CXLType3Dev *ct3d, +#define CXL_MEM_SPARING_FLAGS_QUERY_RESOURCES BIT(0) +#define CXL_MEM_SPARING_FLAGS_HARD_SPARING BIT(1) +#define CXL_MEM_SPARING_FLAGS_SUB_CHANNEL_VALID BIT(2) +#define CXL_MEM_SPARING_FLAGS_NIB_MASK_VALID BIT(3) + +typedef struct CXLMemSparingMaintInPayload { + uint8_t flags; + uint8_t channel; + uint8_t rank; + uint8_t nibble_mask[3]; + uint8_t bank_group; + uint8_t bank; + uint8_t row[3]; + uint16_t column; + uint8_t sub_channel; +} QEMU_PACKED CXLMemSparingMaintInPayload; + +static void cxl_create_mem_sparing_event_records(CXLType3Dev *ct3d, uint8_t maint_op_class, uint8_t maint_op_sub_c= lass, - CXLMaintenance *ent) + CXLMaintenance *ent, + CXLMemSparingMaintInPayload *sparing_pi) { CXLEventSparing event_rec =3D {}; =20 @@ -1615,6 +1852,31 @@ static void cxl_mbox_create_mem_sparing_event_record= s(CXLType3Dev *ct3d, strncpy((char *)event_rec.component_id, (char *)ent->component= _id, sizeof(event_rec.component_id)); } + } else if (sparing_pi) { + event_rec.flags =3D CXL_MSER_FLAGS_QUERY_RESOURCES; + event_rec.result =3D 0; + event_rec.validity_flags =3D CXL_MSER_VALID_CHANNEL | + CXL_MSER_VALID_RANK | + CXL_MSER_VALID_NIB_MASK | + CXL_MSER_VALID_BANK_GROUP | + CXL_MSER_VALID_BANK | + CXL_MSER_VALID_ROW | + CXL_MSER_VALID_COLUMN; + event_rec.res_avail =3D 1; + event_rec.channel =3D sparing_pi->channel; + event_rec.rank =3D sparing_pi->rank; + if (sparing_pi->flags & CXL_MEM_SPARING_FLAGS_NIB_MASK_VALID) { + __builtin_memcpy(event_rec.nibble_mask, sparing_pi->nibble_mas= k, + sizeof(uint32_t)); + } + event_rec.bank_group =3D sparing_pi->bank_group; + event_rec.bank =3D sparing_pi->bank; + event_rec.column =3D sparing_pi->column; + __builtin_memcpy(event_rec.row, sparing_pi->row, sizeof(uint32_t)); + if (sparing_pi->flags & CXL_MEM_SPARING_FLAGS_SUB_CHANNEL_VALID) { + event_rec.sub_channel =3D sparing_pi->sub_channel; + event_rec.validity_flags |=3D CXL_MSER_VALID_SUB_CHANNEL; + } } else { return; } @@ -1626,6 +1888,26 @@ static void cxl_mbox_create_mem_sparing_event_record= s(CXLType3Dev *ct3d, } } =20 +static CXLRetCode cxl_perform_mem_sparing(CXLType3Dev *ct3d, uint8_t sub_c= lass, + void *maint_pi) +{ + switch (sub_class) { + case CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING: + qemu_log("Cacheline Memory Sparing\n"); + return CXL_MBOX_SUCCESS; + case CXL_MEMDEV_MAINT_SUBCLASS_ROW_SPARING: + qemu_log("Row Memory Sparing\n"); + return CXL_MBOX_SUCCESS; + case CXL_MEMDEV_MAINT_SUBCLASS_BANK_SPARING: + qemu_log("Bank Memory Sparing\n"); + return CXL_MBOX_SUCCESS; + case CXL_MEMDEV_MAINT_SUBCLASS_RANK_SPARING: + qemu_log("Rank Memory Sparing\n"); + return CXL_MBOX_SUCCESS; + default: + return CXL_MBOX_INVALID_INPUT; + } +} =20 static void cxl_perform_ppr(CXLType3Dev *ct3d, uint64_t dpa) { @@ -1636,10 +1918,10 @@ static void cxl_perform_ppr(CXLType3Dev *ct3d, uint= 64_t dpa) /* Produce a Memory Sparing Event Record */ if (ct3d->soft_ppr_attrs.sppr_op_mode & CXL_MEMDEV_SPPR_OP_MODE_MEM_SPARING_EV_REC_EN) { - cxl_mbox_create_mem_sparing_event_records(ct3d, + cxl_create_mem_sparing_event_records(ct3d, CXL_MEMDEV_MAINT_CLASS_SPARING, CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARIN= G, - ent); + ent, NULL); } break; } @@ -1663,6 +1945,7 @@ static CXLRetCode cmd_media_perform_maintenance(const= struct cxl_cmd *cmd, uint64_t dpa; uint8_t nibble_mask[3]; } QEMU_PACKED ppr; + CXLMemSparingMaintInPayload mem_sparing_pi; }; } QEMU_PACKED *maint_in =3D (void *)payload_in; CXLType3Dev *ct3d =3D CXL_TYPE3(cci->d); @@ -1688,6 +1971,32 @@ static CXLRetCode cmd_media_perform_maintenance(cons= t struct cxl_cmd *cmd, return CXL_MBOX_INVALID_INPUT; } break; + case CXL_MEMDEV_MAINT_CLASS_SPARING: + if (maint_in->mem_sparing_pi.flags & + CXL_MEM_SPARING_FLAGS_QUERY_RESOURCES) { + /* + * CXL r3.2 sect 8.2.10.7.1.4 - Memory Sparing Maintenance Ope= ration + * Produce Memory Sparing Event record to report resources + * availability. + */ + cxl_create_mem_sparing_event_records(ct3d, maint_in->class, + maint_in->subclass, NULL, + &maint_in->mem_sparing_pi= ); + + return CXL_MBOX_SUCCESS; + } + + switch (maint_in->subclass) { + case CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING: + case CXL_MEMDEV_MAINT_SUBCLASS_ROW_SPARING: + case CXL_MEMDEV_MAINT_SUBCLASS_BANK_SPARING: + case CXL_MEMDEV_MAINT_SUBCLASS_RANK_SPARING: + return cxl_perform_mem_sparing(ct3d, maint_in->subclass, + &maint_in->mem_sparing_pi); + default: + return CXL_MBOX_INVALID_INPUT; + } + break; default: return CXL_MBOX_INVALID_INPUT; } diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 6036c610e6..2149775508 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -990,6 +990,50 @@ static void ct3_realize(PCIDevice *pci_dev, Error **er= rp) .hppr_op_mode =3D CXL_MEMDEV_HPPR_OP_MODE_MEM_SPARING_EV_REC_EN }; =20 + /* Set default value for Cacheline Memory Sparing attributes */ + ct3d->cacheline_sparing_attrs =3D (CXLMemSparingReadAttrs) { + .max_maint_latency =3D 0x5, /* 100 ms */ + .op_caps =3D 0, /* require host involvement */ + .op_mode =3D 0, + .maint_op_class =3D CXL_MEMDEV_MAINT_CLASS_SPARING, + .maint_op_subclass =3D CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING, + .restriction_flags =3D CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG | + CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG, + }; + + /* Set default value for Row Memory Sparing attributes */ + ct3d->row_sparing_attrs =3D (CXLMemSparingReadAttrs) { + .max_maint_latency =3D 0x5, /* 100 ms */ + .op_caps =3D 0, /* require host involvement */ + .op_mode =3D 0, + .maint_op_class =3D CXL_MEMDEV_MAINT_CLASS_SPARING, + .maint_op_subclass =3D CXL_MEMDEV_MAINT_SUBCLASS_ROW_SPARING, + .restriction_flags =3D CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG | + CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG, + }; + + /* Set default value for Bank Memory Sparing attributes */ + ct3d->bank_sparing_attrs =3D (CXLMemSparingReadAttrs) { + .max_maint_latency =3D 0x5, /* 100 ms */ + .op_caps =3D 0, /* require host involvement */ + .op_mode =3D 0, + .maint_op_class =3D CXL_MEMDEV_MAINT_CLASS_SPARING, + .maint_op_subclass =3D CXL_MEMDEV_MAINT_SUBCLASS_BANK_SPARING, + .restriction_flags =3D CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG | + CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG, + }; + + /* Set default value for Rank Memory Sparing attributes */ + ct3d->rank_sparing_attrs =3D (CXLMemSparingReadAttrs) { + .max_maint_latency =3D 0x5, /* 100 ms */ + .op_caps =3D 0, /* require host involvement */ + .op_mode =3D 0, + .maint_op_class =3D CXL_MEMDEV_MAINT_CLASS_SPARING, + .maint_op_subclass =3D CXL_MEMDEV_MAINT_SUBCLASS_RANK_SPARING, + .restriction_flags =3D CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG | + CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG, + }; + return; =20 err_release_cdat: diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index 959049aa46..59f8fa7c24 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -608,6 +608,30 @@ typedef struct CXLMemECSWriteAttrs { CXLMemECSFRUWriteAttrs fru_attrs[CXL_ECS_NUM_MEDIA_FRUS]; } QEMU_PACKED CXLMemECSWriteAttrs; =20 +/* + * CXL r3.2 section 8.2.10.7.2.3, Table 8-134 and 8-135: + * Memory Sparing Feature Readable/Writable Attributes + */ +typedef struct CXLMemSparingReadAttrs { + uint8_t max_maint_latency; + uint16_t op_caps; + uint16_t op_mode; + uint8_t maint_op_class; + uint8_t maint_op_subclass; + uint8_t rsvd[10]; + uint16_t restriction_flags; +} QEMU_PACKED CXLMemSparingReadAttrs; + +typedef struct CXLMemSparingWriteAttrs { + uint16_t op_mode; +} QEMU_PACKED CXLMemSparingWriteAttrs; + +#define CXL_MEMDEV_SPARING_GET_FEATURE_VERSION 0x01 +#define CXL_MEMDEV_SPARING_SET_FEATURE_VERSION 0x01 +#define CXL_MEMDEV_SPARING_SAFE_IN_USE_FLAG BIT(0) +#define CXL_MEMDEV_HARD_SPARING_SUPPORT_FLAG BIT(1) +#define CXL_MEMDEV_SOFT_SPARING_SUPPORT_FLAG BIT(2) + #define DCD_MAX_NUM_REGION 8 =20 typedef struct CXLDCExtentRaw { @@ -735,6 +759,15 @@ struct CXLType3Dev { /* ECS control attributes */ CXLMemECSReadAttrs ecs_attrs; CXLMemECSWriteAttrs ecs_wr_attrs; + /* Memory Sparing control attributes */ + CXLMemSparingReadAttrs cacheline_sparing_attrs; + CXLMemSparingWriteAttrs cacheline_sparing_wr_attrs; + CXLMemSparingReadAttrs row_sparing_attrs; + CXLMemSparingWriteAttrs row_sparing_wr_attrs; + CXLMemSparingReadAttrs bank_sparing_attrs; + CXLMemSparingWriteAttrs bank_sparing_wr_attrs; + CXLMemSparingReadAttrs rank_sparing_attrs; + CXLMemSparingWriteAttrs rank_sparing_wr_attrs; =20 struct dynamic_capacity { HostMemoryBackend *host_dc; diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 3052bc9f18..89f6aad531 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -223,6 +223,11 @@ typedef enum CXLDCEventType { * CXL r3.2 section Table 8-60: Memory Sparing Event Record * All fields little endian. */ + +#define CXL_MSER_FLAGS_QUERY_RESOURCES BIT(0) +#define CXL_MSER_FLAGS_HARD_SPARING BIT(1) +#define CXL_MSER_FLAGS_DEV_INITIATED BIT(2) + #define CXL_MSER_VALID_CHANNEL BIT(0) #define CXL_MSER_VALID_RANK BIT(1) #define CXL_MSER_VALID_NIB_MASK BIT(2) --=20 2.43.0