Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2230818/?format=api
{ "id": 2230818, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2230818/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260430050103.3172190-1-physicalmtea@gmail.com/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/1.1/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260430050103.3172190-1-physicalmtea@gmail.com>", "date": "2026-04-30T05:01:03", "name": "hw/cxl: bound Set Feature cleanup to written extent", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "8d08c214a2447cccb9b3994a8bbc3ad01c09b19f", "submitter": { "id": 93269, "url": "http://patchwork.ozlabs.org/api/1.1/people/93269/?format=api", "name": "Jia Jia", "email": "physicalmtea@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260430050103.3172190-1-physicalmtea@gmail.com/mbox/", "series": [ { "id": 502195, "url": "http://patchwork.ozlabs.org/api/1.1/series/502195/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=502195", "date": "2026-04-30T05:01:03", "name": "hw/cxl: bound Set Feature cleanup to written extent", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/502195/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2230818/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2230818/checks/", "tags": {}, "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=prk+x0cr;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g5hr65LyZz1yHv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 15:02:45 +1000 (AEST)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wIJXk-0000ak-4f; Thu, 30 Apr 2026 01:02:32 -0400", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <physicalmtea@gmail.com>)\n id 1wIJX7-0000FC-Br\n for qemu-devel@nongnu.org; Thu, 30 Apr 2026 01:01:57 -0400", "from mail-pl1-x632.google.com ([2607:f8b0:4864:20::632])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <physicalmtea@gmail.com>)\n id 1wIJWR-00057x-UA\n for qemu-devel@nongnu.org; Thu, 30 Apr 2026 01:01:50 -0400", "by mail-pl1-x632.google.com with SMTP id\n d9443c01a7336-2b24fede2acso3002405ad.3\n for <qemu-devel@nongnu.org>; Wed, 29 Apr 2026 22:01:11 -0700 (PDT)", "from localhost.localdomain ([114.249.134.218])\n by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b988963ed0sm39527405ad.65.2026.04.29.22.01.06\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 29 Apr 2026 22:01:09 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777525270; x=1778130070; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=yQ10o/nhNMp9WiPLO3oSpqcfumGQlVQMd3hRta3eci0=;\n b=prk+x0crdHLN1fKm8sw9lNOCLlurerEG/Kv+XiJy/mPxH53gLKqCTQ69aC/1lC5WRw\n v3bgGr4JzQKn2Q63jhzGYaARJegu+7mIOfJwL5evAeOKB7g8L6hDe5Ry7S6UVmP/tB26\n 9dk05Nxk1b5+/I39bBwaB0BQeRcmYvnD8CMWGUTDxKST1cFdHiQp8bP34UB5v/iSDua3\n okBckwqtMPXCafjzzh5ONI0P8bxXeemxNvP+tbhYxeDBrinY/xy8it+juojv8prD7UF7\n 7cJSenDo9xLQhnA+z7VZeX/KBABH1oqgmmcPVZas49PaPWkOuYdT9nTIitlNLOiDraJd\n x3qg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777525270; x=1778130070;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=yQ10o/nhNMp9WiPLO3oSpqcfumGQlVQMd3hRta3eci0=;\n b=LtRHJiIH23TpeEt/46v3l/HzXuX9umbcCV3lPWtHi1M3ghsEyFguNDvk1CfFqB27cs\n nvmnrLAAKt9NpyqizyjdADLlYo+aHrrNdPROxWf24THWH+RIy0xLb5/Vfi9VBzZ8tZuc\n cR6FaW7JzIFLa3dmt3i2OkdxRbAK5D5Sb8FsD+u02u2IO12vMch0GztiKK56B3TO7B4a\n pPMfKQXpjE7ryK9BRbANln563+9iujKnYCzen1Vv3J/NaCMsLMhiuMKpBSfSgl+29C+q\n 6wgw+tX8eQ/L8yzREB7PXfmoNuzI17hBVtT8t4GUW6JKo5Cizp8klEPpWXaJ0GBUR1V4\n pK/A==", "X-Gm-Message-State": "AOJu0YwH4lEJ2SXtKjWEp9jDQJf+cyWJ4fgbR+SqERqv9J8ud9M3McHL\n Mkkw4sjV0ZpUbtPBIfnahbfQjRvMRChxKUCLBwHrcMMH1MPnF0U2Zs0lr97Ql15bDPgKnQ==", "X-Gm-Gg": "AeBDietN5x57hmtK6m8wIp6WUDtXlYq48Sgo2f2JlfYFi/YPJNRBiL/vHmsKu96+X23\n UISGS/pYpEUME0Lf6W+6rU1eX4TY7zfwSNgeVuxKrOpwNgbU4IPEhrd2l1UXG6FbjHzYLnWH2iY\n j+wNH2otiFtkwqulGFHASonWY1rqecSoXviF7EynSHADMT1xIbLCfD5r2qQZN3j/gcqlQBiqNar\n CzFWc6njBS4Ru0LhSOqURppm/kYNYzoAV8erOn6Qtcks7aKvf9dkf+ZllOX5izzePrzGY2KtA+g\n w5geJ31l1nLN1L7BiBLmbLq2abJbk1hxKbOgoMSPtvhV1p6nu+zJasmew2bXZmH3SSoBzvbwrNe\n v7Z/Ck1+5P0o2PGp7amVo5w+V1i49gmU8u3Jm/5bqdmRkKdPqtNaW5PH8ati1E5sO3ytlqX702I\n Q2oIr07oX/xk0XQ3Y7Np7nqQ008PqkDgRCOfbLn3pmcQ1EHPU1m64=", "X-Received": "by 2002:a17:903:3c4f:b0:2b0:6e6a:8504 with SMTP id\n d9443c01a7336-2b9a24b954fmr12675645ad.27.1777525269442;\n Wed, 29 Apr 2026 22:01:09 -0700 (PDT)", "From": "Jia Jia <physicalmtea@gmail.com>", "To": "qemu-devel@nongnu.org", "Cc": "jonathan.cameron@huawei.com, fan.ni@samsung.com, farosas@suse.de,\n lvivier@redhat.com, pbonzini@redhat.com", "Subject": "[PATCH] hw/cxl: bound Set Feature cleanup to written extent", "Date": "Thu, 30 Apr 2026 13:01:03 +0800", "Message-Id": "<20260430050103.3172190-1-physicalmtea@gmail.com>", "X-Mailer": "git-send-email 2.34.1", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2607:f8b0:4864:20::632;\n envelope-from=physicalmtea@gmail.com; helo=mail-pl1-x632.google.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n 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": "qemu development <qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org" }, "content": "cmd_features_set_feature() validates each fragment against the target\nwrite-attribute buffer, but it tracks data_size as the sum of every\nfragment copied so far.\n\nThat becomes a problem at transfer completion. Cleanup uses data_size as\nits memset() length, so a sequence of legal partial transfers can keep\nrewriting the same small range while growing data_size far beyond the\nfeature buffer that is actually being updated.\n\nOn an ASan build, repeatedly sending 2-byte rank_sparing fragments at\noffset 0 and then finishing aborts the host with:\n\n ERROR: AddressSanitizer: heap-buffer-overflow\n WRITE of size 1144\n #0 __interceptor_memset\n #1 cmd_features_set_feature ../hw/cxl/cxl-mailbox-utils.c:1961\n #2 cxl_process_cci_message ../hw/cxl/cxl-mailbox-utils.c:4642\n #3 mailbox_reg_write ../hw/cxl/cxl-device-utils.c:209\n\nFix this by tracking the maximum written extent instead of the cumulative\nnumber of copied bytes. That keeps cleanup bounded to the actual\nwrite-attribute window without changing the rest of the transfer flow.\n\nAdd a qtest that confirms a multipart bank_sparing transfer does not\nclobber adjacent rank_sparing state during cleanup.\n\nResolves: https://gitlab.com/qemu-project/qemu/-/issues/3461\nSigned-off-by: Jia Jia <physicalmtea@gmail.com>\n\n---\n hw/cxl/cxl-mailbox-utils.c | 11 +---\n tests/qtest/cxl-test.c | 119 ++++++++++++++++++++++++++++++++++++-\n 2 files changed, 121 insertions(+), 9 deletions(-)", "diff": "diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c\nindex ce139e30eb..8346177b79 100644\n--- a/hw/cxl/cxl-mailbox-utils.c\n+++ b/hw/cxl/cxl-mailbox-utils.c\n@@ -1769,7 +1769,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n memcpy((uint8_t *)&ct3d->patrol_scrub_wr_attrs + hdr->offset,\n ps_write_attrs,\n bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1796,7 +1795,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n memcpy((uint8_t *)&ct3d->ecs_wr_attrs + hdr->offset,\n ecs_write_attrs,\n bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1820,7 +1818,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n }\n memcpy((uint8_t *)&ct3d->soft_ppr_wr_attrs + hdr->offset,\n sppr_write_attrs, bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1842,7 +1839,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n }\n memcpy((uint8_t *)&ct3d->hard_ppr_wr_attrs + hdr->offset,\n hppr_write_attrs, bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1864,7 +1860,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n }\n memcpy((uint8_t *)&ct3d->cacheline_sparing_wr_attrs + hdr->offset,\n mem_sparing_write_attrs, bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1885,7 +1880,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n }\n memcpy((uint8_t *)&ct3d->row_sparing_wr_attrs + hdr->offset,\n mem_sparing_write_attrs, bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1906,7 +1900,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n }\n memcpy((uint8_t *)&ct3d->bank_sparing_wr_attrs + hdr->offset,\n mem_sparing_write_attrs, bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1927,7 +1920,6 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n }\n memcpy((uint8_t *)&ct3d->rank_sparing_wr_attrs + hdr->offset,\n mem_sparing_write_attrs, bytes_to_copy);\n- set_feat_info->data_size += bytes_to_copy;\n \n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER) {\n@@ -1938,6 +1930,9 @@ static CXLRetCode cmd_features_set_feature(const struct cxl_cmd *cmd,\n return CXL_MBOX_UNSUPPORTED;\n }\n \n+ set_feat_info->data_size = MAX(set_feat_info->data_size,\n+ (size_t)end_offset);\n+\n if (data_transfer_flag == CXL_SET_FEATURE_FLAG_FULL_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER ||\n data_transfer_flag == CXL_SET_FEATURE_FLAG_ABORT_DATA_TRANSFER) {\ndiff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c\nindex a9fcd98736..ed222aca4b 100644\n--- a/tests/qtest/cxl-test.c\n+++ b/tests/qtest/cxl-test.c\n@@ -99,6 +99,21 @@ typedef struct QEMU_PACKED CXLSetFeatureInHeaderTest {\n uint8_t rsvd[9];\n } CXLSetFeatureInHeaderTest;\n \n+typedef struct QEMU_PACKED CXLGetFeatureInHeaderTest {\n+ uint8_t uuid[16];\n+ uint16_t offset;\n+ uint16_t count;\n+ uint8_t selection;\n+} CXLGetFeatureInHeaderTest;\n+\n+enum {\n+ CXL_TEST_GET_FEATURE_SEL_CURRENT_VALUE = 0,\n+ CXL_TEST_SET_FEATURE_FLAG_FULL_DATA_TRANSFER = 0,\n+ CXL_TEST_SET_FEATURE_FLAG_INITIATE_DATA_TRANSFER = 1,\n+ CXL_TEST_SET_FEATURE_FLAG_CONTINUE_DATA_TRANSFER = 2,\n+ CXL_TEST_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER = 3,\n+};\n+\n static void cxl_basic_hb(void)\n {\n qtest_start(\"-machine q35,cxl=on\");\n@@ -177,15 +192,37 @@ static uint16_t cxl_test_t3d_mailbox_errno(void)\n \n static void cxl_test_fill_set_feature_header(CXLSetFeatureInHeaderTest *hdr,\n const uint8_t uuid[16],\n+ uint32_t flags,\n uint16_t offset,\n uint8_t version)\n {\n memset(hdr, 0, sizeof(*hdr));\n memcpy(hdr->uuid, uuid, 16);\n+ hdr->flags = cpu_to_le32(flags);\n hdr->offset = cpu_to_le16(offset);\n hdr->version = version;\n }\n \n+static void cxl_test_fill_get_feature_header(CXLGetFeatureInHeaderTest *hdr,\n+ const uint8_t uuid[16],\n+ uint16_t offset,\n+ uint16_t count)\n+{\n+ memset(hdr, 0, sizeof(*hdr));\n+ memcpy(hdr->uuid, uuid, 16);\n+ hdr->offset = cpu_to_le16(offset);\n+ hdr->count = cpu_to_le16(count);\n+ hdr->selection = CXL_TEST_GET_FEATURE_SEL_CURRENT_VALUE;\n+}\n+\n+static void cxl_test_t3d_submit_get_feature(const void *payload, size_t len)\n+{\n+ memwrite(cxl_test_t3d_payload_base(), payload, len);\n+ writeq(cxl_test_t3d_mailbox_base() + A_CXL_DEV_MAILBOX_CMD,\n+ ((uint64_t)len << 16) | (0x05 << 8) | 0x01);\n+ writel(cxl_test_t3d_mailbox_base() + A_CXL_DEV_MAILBOX_CTRL, 1);\n+}\n+\n static void cxl_t3d_set_feature_rejects_oversized_rank_sparing(void)\n {\n static const uint8_t rank_sparing_uuid[16] = {\n@@ -203,7 +240,7 @@ static void cxl_t3d_set_feature_rejects_oversized_rank_sparing(void)\n qtest_start(cmdline->str);\n cxl_test_t3d_enable_bar2();\n \n- cxl_test_fill_set_feature_header(hdr, rank_sparing_uuid, 0,\n+ cxl_test_fill_set_feature_header(hdr, rank_sparing_uuid, 0, 0,\n CXL_MEMDEV_SPARING_SET_FEATURE_VERSION);\n memset(payload + sizeof(*hdr), 0x41,\n sizeof(payload) - sizeof(*hdr));\n@@ -215,6 +252,84 @@ static void cxl_t3d_set_feature_rejects_oversized_rank_sparing(void)\n rmdir(tmpfs);\n }\n \n+static void cxl_t3d_set_feature_cleanup_stays_within_feature_state(void)\n+{\n+ static const uint8_t bank_sparing_uuid[16] = {\n+ 0x36, 0x96, 0xb7, 0x78, 0xac, 0x90, 0x64, 0x4b,\n+ 0xa4, 0xef, 0xfa, 0xac, 0x5d, 0x18, 0xa8, 0x63,\n+ };\n+ static const uint8_t rank_sparing_uuid[16] = {\n+ 0x34, 0xdb, 0xaf, 0xf5, 0x05, 0x52, 0x42, 0x81,\n+ 0x8f, 0x76, 0xda, 0x0b, 0x5e, 0x7a, 0x76, 0xa7,\n+ };\n+ g_autoptr(GString) cmdline = g_string_new(NULL);\n+ g_autofree const char *tmpfs = NULL;\n+ uint8_t set_payload[sizeof(CXLSetFeatureInHeaderTest) + 2] = { 0 };\n+ uint8_t get_payload[sizeof(CXLGetFeatureInHeaderTest)] = { 0 };\n+ uint8_t out[2];\n+ CXLSetFeatureInHeaderTest *set_hdr = (void *)set_payload;\n+ CXLGetFeatureInHeaderTest *get_hdr = (void *)get_payload;\n+ int i;\n+\n+ tmpfs = g_dir_make_tmp(\"cxl-test-XXXXXX\", NULL);\n+ g_string_printf(cmdline, QEMU_T3D_DIRECT_PMEM, tmpfs, tmpfs);\n+\n+ qtest_start(cmdline->str);\n+ cxl_test_t3d_enable_bar2();\n+\n+ cxl_test_fill_set_feature_header(\n+ set_hdr, rank_sparing_uuid,\n+ CXL_TEST_SET_FEATURE_FLAG_FULL_DATA_TRANSFER, 0,\n+ CXL_MEMDEV_SPARING_SET_FEATURE_VERSION);\n+ set_payload[sizeof(*set_hdr)] = 0x34;\n+ set_payload[sizeof(*set_hdr) + 1] = 0x12;\n+ cxl_test_t3d_submit_set_feature(set_payload, sizeof(set_payload));\n+ g_assert_cmphex(cxl_test_t3d_mailbox_errno(), ==, CXL_MBOX_SUCCESS);\n+\n+ cxl_test_fill_set_feature_header(set_hdr, bank_sparing_uuid,\n+ CXL_TEST_SET_FEATURE_FLAG_INITIATE_DATA_TRANSFER,\n+ 0,\n+ CXL_MEMDEV_SPARING_SET_FEATURE_VERSION);\n+ set_payload[sizeof(*set_hdr)] = 0x78;\n+ set_payload[sizeof(*set_hdr) + 1] = 0x56;\n+ cxl_test_t3d_submit_set_feature(set_payload, sizeof(set_payload));\n+ g_assert_cmphex(cxl_test_t3d_mailbox_errno(), ==, CXL_MBOX_SUCCESS);\n+\n+ /* Repeating the same 2-byte fragment must not clobber adjacent state. */\n+ for (i = 0; i < 2; i++) {\n+ cxl_test_fill_set_feature_header(\n+ set_hdr, bank_sparing_uuid,\n+ CXL_TEST_SET_FEATURE_FLAG_CONTINUE_DATA_TRANSFER,\n+ 0, CXL_MEMDEV_SPARING_SET_FEATURE_VERSION);\n+ set_payload[sizeof(*set_hdr)] = 0xaa;\n+ set_payload[sizeof(*set_hdr) + 1] = 0xbb;\n+ cxl_test_t3d_submit_set_feature(set_payload, sizeof(set_payload));\n+ g_assert_cmphex(cxl_test_t3d_mailbox_errno(), ==, CXL_MBOX_SUCCESS);\n+ }\n+\n+ cxl_test_fill_set_feature_header(set_hdr, bank_sparing_uuid,\n+ CXL_TEST_SET_FEATURE_FLAG_FINISH_DATA_TRANSFER,\n+ 0,\n+ CXL_MEMDEV_SPARING_SET_FEATURE_VERSION);\n+ set_payload[sizeof(*set_hdr)] = 0xcc;\n+ set_payload[sizeof(*set_hdr) + 1] = 0xdd;\n+ cxl_test_t3d_submit_set_feature(set_payload, sizeof(set_payload));\n+ g_assert_cmphex(cxl_test_t3d_mailbox_errno(), ==, CXL_MBOX_SUCCESS);\n+\n+ cxl_test_fill_get_feature_header(get_hdr, rank_sparing_uuid,\n+ offsetof(CXLMemSparingReadAttrs, op_mode),\n+ 2);\n+ cxl_test_t3d_submit_get_feature(get_payload, sizeof(get_payload));\n+ g_assert_cmphex(cxl_test_t3d_mailbox_errno(), ==, CXL_MBOX_SUCCESS);\n+\n+ memread(cxl_test_t3d_payload_base(), out, sizeof(out));\n+ g_assert_cmphex(out[0], ==, 0x34);\n+ g_assert_cmphex(out[1], ==, 0x12);\n+\n+ qtest_end();\n+ rmdir(tmpfs);\n+}\n+\n static void cxl_t3d_deprecated(void)\n {\n g_autoptr(GString) cmdline = g_string_new(NULL);\n@@ -337,6 +452,8 @@ int main(int argc, char **argv)\n qtest_add_func(\"/pci/cxl/type3_device_vmem_lsa\", cxl_t3d_volatile_lsa);\n qtest_add_func(\"/pci/cxl/type3_device_set_feature_rank_sparing_bounds\",\n cxl_t3d_set_feature_rejects_oversized_rank_sparing);\n+ qtest_add_func(\"/pci/cxl/type3_device_set_feature_cleanup_bounds\",\n+ cxl_t3d_set_feature_cleanup_stays_within_feature_state);\n qtest_add_func(\"/pci/cxl/rp_x2_type3_x2\", cxl_1pxb_2rp_2t3d);\n qtest_add_func(\"/pci/cxl/pxb_x2_root_port_x4_type3_x4\",\n cxl_2pxb_4rp_4t3d);\n", "prefixes": [] }