From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9B9E1FBEB0 for ; Thu, 4 Sep 2025 23:24:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757028296; cv=none; b=IhZxCEqqiWA3PfZzC6PNr5vlGlqCJ53aGDKoYuo1wHspqCbuUbXgqiMQW30sqWb4JkRRre3rL6pG3OXgRJzEdehCslsFzdXOQcd7dRNLY60DVpaLz3wppsnP6+QVOCmnNG/kanCMj1dapcgGZz8Seg6WvhdGH8dGBYfvrfBY2H8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757028296; c=relaxed/simple; bh=HcSn2ODuVqM2BfpuTR3dCP6AC+5HOd5kKeEIPWTVJrY=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=Wg7qrOsZSU+jrEMRNs7WuCGDFW8KGmP/iTkHJul55XvE7xzlV9UiLIu/g30dCZSGeo4l16IdvQPQEcsIidFO8JrYLlp43k0tOJaxns44sxopd/IkQ4TzhNZrncxWbPATEhiFbfpWRH58rTZ6ue+3djgoWhFgyKYVnRJ5qpAVG4c= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=cZLZsCl4; arc=none smtp.client-ip=198.175.65.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="cZLZsCl4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1757028294; x=1788564294; h=message-id:date:mime-version:subject:to:cc:references: from:in-reply-to:content-transfer-encoding; bh=HcSn2ODuVqM2BfpuTR3dCP6AC+5HOd5kKeEIPWTVJrY=; b=cZLZsCl4u0RqbrxZcIOLgqCe6iLf/I1AU1gjovHCizVophmdEWFc52Z7 pg3zsQpxdqrw2rrql9zL4RkGHb70feZAoMkjrLRIrQe4+kvi3ETAsXtEJ B6w+0yelzBp+1OygwZefuRPQi/6FUeLHFQFYpN8NztGDdkooVkP8KkujP R5btJcXscyVk2igM3cs3/USNHVPvB/MXlkyUjhDKkSJnMxeO64HTDMLen 6jkmxL115Do2jmcmj/goXIWqU0iH1DUuAA1QZtai55drvH4HC4MJehecX yk4PfGDWLtAPSgj2SEP9RejfQbElsl3PcgbhqCDhcJk3Nlq75ymb69gIS g==; X-CSE-ConnectionGUID: Fi5t7Z2uRtacUkr7/ERY0g== X-CSE-MsgGUID: 5FUoq7GDSE2w2C2jTpxJDg== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="59450655" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="59450655" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Sep 2025 16:24:54 -0700 X-CSE-ConnectionGUID: YZmvzLigTNGglhrxLO2XsQ== X-CSE-MsgGUID: DvdVpIXFQGKcTFxSK93cvQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.18,239,1751266800"; d="scan'208";a="171597888" Received: from cmdeoliv-mobl4.amr.corp.intel.com (HELO [10.125.110.24]) ([10.125.110.24]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Sep 2025 16:24:52 -0700 Message-ID: Date: Thu, 4 Sep 2025 16:24:50 -0700 Precedence: bulk X-Mailing-List: linux-cxl@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v2 3/3] cxl/test: Add cxl_translate module for address translation testing To: Alison Schofield , Davidlohr Bueso , Jonathan Cameron , Vishal Verma , Ira Weiny , Dan Williams Cc: linux-cxl@vger.kernel.org References: Content-Language: en-US From: Dave Jiang In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 8/29/25 12:21 AM, Alison Schofield wrote: > Add a loadable test module that validates CXL address translation > calculations using parameterized test vectors. The module tests both > host to device and device to host address translations for Modulo and > XOR interleave arithmetic. > > Test vectors are provided as module parameters in the format: > "dpa pos r_eiw r_eig hb_ways math expected_spa" > > The module performs round-trip validation: > 1. Translate a DPA and position to a SPA > 2. Verify the result matches expected SPA > 3. Translate that SPA back to a DPA and position > 4. Verify round-trip consistency > > The module accesses the refactored translation functions through the > exports made available only to CXL test modules. > > Signed-off-by: Alison Schofield > Reviewed-by: Jonathan Cameron Reviewed-by: Dave Jiang > --- > tools/testing/cxl/Kbuild | 2 + > tools/testing/cxl/cxl_acpi_exports.c | 7 + > tools/testing/cxl/cxl_core_exports.c | 12 + > tools/testing/cxl/cxl_test.h | 18 ++ > tools/testing/cxl/test/Kbuild | 2 + > tools/testing/cxl/test/cxl_translate.c | 303 +++++++++++++++++++++++++ > 6 files changed, 344 insertions(+) > create mode 100644 tools/testing/cxl/cxl_acpi_exports.c > create mode 100644 tools/testing/cxl/cxl_test.h > create mode 100644 tools/testing/cxl/test/cxl_translate.c > > diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild > index d07f14cb7aa4..95397434fc12 100644 > --- a/tools/testing/cxl/Kbuild > +++ b/tools/testing/cxl/Kbuild > @@ -21,6 +21,7 @@ CXL_SRC := $(DRIVERS)/cxl > CXL_CORE_SRC := $(DRIVERS)/cxl/core > ccflags-y := -I$(srctree)/drivers/cxl/ > ccflags-y += -D__mock=__weak > +ccflags-y += -D__mock_export= > ccflags-y += -DTRACE_INCLUDE_PATH=$(CXL_CORE_SRC) -I$(srctree)/drivers/cxl/core/ > > obj-m += cxl_acpi.o > @@ -29,6 +30,7 @@ cxl_acpi-y := $(CXL_SRC)/acpi.o > cxl_acpi-y += mock_acpi.o > cxl_acpi-y += config_check.o > cxl_acpi-y += cxl_acpi_test.o > +cxl_acpi-y += cxl_acpi_exports.o > > obj-m += cxl_pmem.o > > diff --git a/tools/testing/cxl/cxl_acpi_exports.c b/tools/testing/cxl/cxl_acpi_exports.c > new file mode 100644 > index 000000000000..b66fa0696db1 > --- /dev/null > +++ b/tools/testing/cxl/cxl_acpi_exports.c > @@ -0,0 +1,7 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright(c) 2022 Intel Corporation. All rights reserved. */ > + > +#include "cxl_test.h" > + > +/* Export of cxl_acpi (acpi.o) symbol used only by cxl_translate */ > +EXPORT_SYMBOL_NS_GPL(cxl_do_xormap_calc, "CXL"); > diff --git a/tools/testing/cxl/cxl_core_exports.c b/tools/testing/cxl/cxl_core_exports.c > index f088792a8925..4927797dfa31 100644 > --- a/tools/testing/cxl/cxl_core_exports.c > +++ b/tools/testing/cxl/cxl_core_exports.c > @@ -2,6 +2,18 @@ > /* Copyright(c) 2022 Intel Corporation. All rights reserved. */ > > #include "cxl.h" > +#include "cxl_test.h" > > /* Exporting of cxl_core symbols that are only used by cxl_test */ > EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, "CXL"); > + > +/* > + * Exporting of cxl_core symbols used only by the cxl_translate module. > + * > + * Note: checkpatch warns about EXPORT_SYMBOL placement, but this is > + * the established pattern for CXL test exports where functions are > + * defined in drivers/cxl/core/. > + */ > +EXPORT_SYMBOL_NS_GPL(cxl_calculate_hpa_offset, "CXL"); > +EXPORT_SYMBOL_NS_GPL(cxl_calculate_dpa_offset, "CXL"); > +EXPORT_SYMBOL_NS_GPL(cxl_calculate_position, "CXL"); > diff --git a/tools/testing/cxl/cxl_test.h b/tools/testing/cxl/cxl_test.h > new file mode 100644 > index 000000000000..94777d999cb3 > --- /dev/null > +++ b/tools/testing/cxl/cxl_test.h > @@ -0,0 +1,18 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > + > +#ifndef __CXL_TEST_H__ > +#define __CXL_TEST_H__ > + > +#include > + > +/* Function declarations only visible to test code */ > + > +/* XOR calculation function from drivers/cxl/acpi.c */ > +u64 cxl_do_xormap_calc(struct cxl_cxims_data *cximsd, u64 addr, int hbiw); > + > +/* Address translation functions from drivers/cxl/core/region.c */ > +u64 cxl_calculate_hpa_offset(u64 dpa_offset, int pos, u8 eiw, u16 eig); > +u64 cxl_calculate_dpa_offset(u64 hpa_offset, u8 eiw, u16 eig); > +int cxl_calculate_position(u64 hpa_offset, u8 eiw, u16 eig); > + > +#endif > diff --git a/tools/testing/cxl/test/Kbuild b/tools/testing/cxl/test/Kbuild > index 6b1927897856..d55973e61fdd 100644 > --- a/tools/testing/cxl/test/Kbuild > +++ b/tools/testing/cxl/test/Kbuild > @@ -5,6 +5,8 @@ obj-m += cxl_test.o > obj-m += cxl_mock.o > obj-m += cxl_mock_mem.o > > +obj-m += cxl_translate.o > + > cxl_test-y := cxl.o > cxl_mock-y := mock.o > cxl_mock_mem-y := mem.o > diff --git a/tools/testing/cxl/test/cxl_translate.c b/tools/testing/cxl/test/cxl_translate.c > new file mode 100644 > index 000000000000..f7076f4069d4 > --- /dev/null > +++ b/tools/testing/cxl/test/cxl_translate.c > @@ -0,0 +1,303 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +// Copyright(c) 2025 Intel Corporation. All rights reserved. > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "../cxl_test.h" > + > +/* Maximum number of test vectors and entry length */ > +#define MAX_TABLE_ENTRIES 128 > +#define MAX_ENTRY_LEN 128 > + > +/* Expected number of parameters in each test vector */ > +#define EXPECTED_PARAMS 7 > + > +/* Module parameters for test vectors */ > +static char *table[MAX_TABLE_ENTRIES]; > +static int table_num; > + > +/* Interleave Arithmetic */ > +#define MODULO_MATH 0 > +#define XOR_MATH 1 > + > +/* > + * XOR mapping configuration > + * The test data sets all use the same set of xormaps. When additional > + * data sets arrive for validation, this static setup will need to > + * be changed to accept xormaps as additional parameters. > + */ > +struct cxl_cxims_data *cximsd; > +static u64 xormaps[] = { > + 0x2020900, > + 0x4041200, > + 0x1010400, > + 0x800, > +}; > + > +static int nr_maps = ARRAY_SIZE(xormaps); > + > +/** > + * to_hpa - calculate an HPA offset from a DPA offset and position > + * > + * dpa_offset: device physical address offset > + * pos: devices position in interleave > + * r_eiw: region encoded interleave ways > + * r_eig: region encoded interleave granularity > + * hb_ways: host bridge interleave ways > + * math: interleave arithmetic (MODULO_MATH or XOR_MATH) > + * > + * Returns: host physical address offset > + */ > +static u64 to_hpa(u64 dpa_offset, int pos, u8 r_eiw, u16 r_eig, u8 hb_ways, > + u8 math) > +{ > + u64 hpa_offset; > + > + /* Calculate base HPA offset from DPA and position */ > + hpa_offset = cxl_calculate_hpa_offset(dpa_offset, pos, r_eiw, r_eig); > + > + /* Apply XOR mapping if specified */ > + if (math == XOR_MATH) > + hpa_offset = cxl_do_xormap_calc(cximsd, hpa_offset, hb_ways); > + > + return hpa_offset; > +} > + > +/** > + * to_dpa - translate an HPA offset to DPA offset > + * > + * hpa_offset: host physical address offset > + * r_eiw: region encoded interleave ways > + * r_eig: region encoded interleave granularity > + * hb_ways: host bridge interleave ways > + * math: interleave arithmetic (MODULO_MATH or XOR_MATH) > + * > + * Returns: device physical address offset > + */ > +static u64 to_dpa(u64 hpa_offset, u8 r_eiw, u16 r_eig, u8 hb_ways, u8 math) > +{ > + u64 offset = hpa_offset; > + > + /* Reverse XOR mapping if specified */ > + if (math == XOR_MATH) > + offset = cxl_do_xormap_calc(cximsd, hpa_offset, hb_ways); > + > + return cxl_calculate_dpa_offset(offset, r_eiw, r_eig); > +} > + > +/** > + * to_pos - extract an interleave position from an HPA offset > + * > + * hpa_offset: host physical address offset > + * r_eiw: region encoded interleave ways > + * r_eig: region encoded interleave granularity > + * hb_ways: host bridge interleave ways > + * math: interleave arithmetic (MODULO_MATH or XOR_MATH) > + * > + * Returns: devices position in region interleave > + */ > +static u64 to_pos(u64 hpa_offset, u8 r_eiw, u16 r_eig, u8 hb_ways, u8 math) > +{ > + u64 offset = hpa_offset; > + > + /* Reverse XOR mapping if specified */ > + if (math == XOR_MATH) > + offset = cxl_do_xormap_calc(cximsd, hpa_offset, hb_ways); > + > + return cxl_calculate_position(offset, r_eiw, r_eig); > +} > + > +/** > + * run_translation_test - execute forward and reverse translations > + * > + * @dpa: device physical address > + * @pos: expected position in region interleave > + * @r_eiw: region encoded interleave ways > + * @r_eig: region encoded interleave granularity > + * @hb_ways: host bridge interleave ways > + * @math: interleave arithmetic (MODULO_MATH or XOR_MATH) > + * @expect_spa: expected system physical address > + * > + * Returns: 0 on success, -1 on failure > + */ > +static int run_translation_test(u64 dpa, int pos, u8 r_eiw, u16 r_eig, > + u8 hb_ways, int math, u64 expect_hpa) > +{ > + u64 translated_spa, reverse_dpa; > + int reverse_pos; > + > + /* Test Device to Host translation: DPA + POS -> SPA */ > + translated_spa = to_hpa(dpa, pos, r_eiw, r_eig, hb_ways, math); > + if (translated_spa != expect_hpa) { > + pr_err("Device to host failed: expected HPA %llu, got %llu\n", > + expect_hpa, translated_spa); > + return -1; > + } > + > + /* Test Host to Device DPA translation: SPA -> DPA */ > + reverse_dpa = to_dpa(translated_spa, r_eiw, r_eig, hb_ways, math); > + if (reverse_dpa != dpa) { > + pr_err("Host to Device DPA failed: expected %llu, got %llu\n", > + dpa, reverse_dpa); > + return -1; > + } > + > + /* Test Host to Device Position translation: SPA -> POS */ > + reverse_pos = to_pos(translated_spa, r_eiw, r_eig, hb_ways, math); > + if (reverse_pos != pos) { > + pr_err("Position lookup failed: expected %d, got %d\n", pos, > + reverse_pos); > + return -1; > + } > + > + return 0; > +} > + > +/** > + * parse_test_vector - parse a single test vector string > + * > + * entry: test vector string to parse > + * dpa: device physical address > + * pos: expected position in region interleave > + * r_eiw: region encoded interleave ways > + * r_eig: region encoded interleave granularity > + * hb_ways: host bridge interleave ways > + * math: interleave arithmetic (MODULO_MATH or XOR_MATH) > + * expect_spa: expected system physical address > + * > + * Returns: 0 on success, negative error code on failure > + */ > +static int parse_test_vector(const char *entry, u64 *dpa, int *pos, u8 *r_eiw, > + u16 *r_eig, u8 *hb_ways, int *math, > + u64 *expect_hpa) > +{ > + unsigned int tmp_r_eiw, tmp_r_eig, tmp_hb_ways; > + int parsed; > + > + parsed = sscanf(entry, "%llu %d %u %u %u %d %llu", dpa, pos, &tmp_r_eiw, > + &tmp_r_eig, &tmp_hb_ways, math, expect_hpa); > + > + if (parsed != EXPECTED_PARAMS) { > + pr_err("Parse error: expected %d parameters, got %d in '%s'\n", > + EXPECTED_PARAMS, parsed, entry); > + return -EINVAL; > + } > + if (tmp_r_eiw > U8_MAX || tmp_r_eig > U16_MAX || tmp_hb_ways > U8_MAX) { > + pr_err("Parameter overflow in entry: '%s'\n", entry); > + return -ERANGE; > + } > + if (*math != MODULO_MATH && *math != XOR_MATH) { > + pr_err("Invalid math type %d in entry: '%s'\n", *math, entry); > + return -EINVAL; > + } > + *r_eiw = tmp_r_eiw; > + *r_eig = tmp_r_eig; > + *hb_ways = tmp_hb_ways; > + > + return 0; > +} > + > +/* > + * setup_xor_mapping - Initialize XOR mapping data structure > + * > + * The test data sets all use the same set of xormaps. When additional > + * data sets arrive for validation, this static setup will need to > + * be changed to accept xormaps as additional parameters. > + * > + * Returns: 0 on success, negative error code on failure > + */ > +static int setup_xor_mapping(void) > +{ > + if (nr_maps <= 0) > + return -EINVAL; > + > + cximsd = kzalloc(struct_size(cximsd, xormaps, nr_maps), GFP_KERNEL); > + if (!cximsd) > + return -ENOMEM; > + > + memcpy(cximsd->xormaps, xormaps, nr_maps * sizeof(*cximsd->xormaps)); > + cximsd->nr_maps = nr_maps; > + > + return 0; > +} > + > +/* > + * cxl_translate_init - parse test vectors and kicks off translation tests > + * > + * Returns: 0 on success, negative error code on failure > + */ > +static int __init cxl_translate_init(void) > +{ > + int ret, i; > + > + /* Validate module parameters */ > + if (table_num == 0) { > + pr_err("No test vectors provided\n"); > + return -EINVAL; > + } > + > + pr_info("CXL translate test module loaded with %d test vectors\n", > + table_num); > + > + ret = setup_xor_mapping(); > + if (ret) > + return ret; > + > + /* Process each test vector */ > + for (i = 0; i < table_num; i++) { > + u64 dpa, expect_spa; > + int pos, math; > + u8 r_eiw, hb_ways; > + u16 r_eig; > + > + pr_debug("Processing test vector %d: '%s'\n", i, table[i]); > + > + /* Parse the test vector */ > + ret = parse_test_vector(table[i], &dpa, &pos, &r_eiw, &r_eig, > + &hb_ways, &math, &expect_spa); > + if (ret) { > + pr_err("CXL Translate Test %d: FAIL\n" > + " Failed to parse test vector '%s'\n", > + i, table[i]); > + continue; > + } > + /* Run the translation test */ > + ret = run_translation_test(dpa, pos, r_eiw, r_eig, hb_ways, > + math, expect_spa); > + if (ret) { > + pr_err("CXL Translate Test %d: FAIL\n" > + " dpa=%llu pos=%d r_eiw=%u r_eig=%u hb_ways=%u math=%s expect_spa=%llu\n", > + i, dpa, pos, r_eiw, r_eig, hb_ways, > + (math == XOR_MATH) ? "XOR" : "MODULO", > + expect_spa); > + } else { > + pr_info("CXL Translate Test %d: PASS\n", i); > + } > + } > + > + pr_info("CXL translate test completed\n"); > + return 0; > +} > + > +static void __exit cxl_translate_exit(void) > +{ > + kfree(cximsd); > + > + pr_info("CXL translate test module unloaded\n"); > +} > + > +module_param_array(table, charp, &table_num, 0444); > +MODULE_PARM_DESC(table, "Test vectors as space-separated decimal strings"); > + > +MODULE_LICENSE("GPL"); > +MODULE_DESCRIPTION("cxl_test: cxl address translation test module"); > +MODULE_IMPORT_NS("CXL"); > + > +module_init(cxl_translate_init); > +module_exit(cxl_translate_exit);