From nobody Mon Oct 6 04:57:12 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 39E862DEA80; Thu, 24 Jul 2025 14:25:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367111; cv=none; b=Q9Hvk9cg1nu/f94Nsp5hwJrMZSuWBWPO0uRe7NzZpHi4Ep/wA0BeOne+EpkbOLMD+KSJr4O/S76BApabkNgInODWGJ0LiFzm2gCg1cKcGIQcsMdWcSLgPawxlfDMgQcY9J4LYlNvirFDw6LoNQFMmQJ+fMMSJPo7nRKzxHaAyrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367111; c=relaxed/simple; bh=15ZHWHaWRSiwY6M4f3gJGxIPd+lGYskyqPDvKluQqrs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GJSBwR4jtKzHaMxnoRzq4qdJaFpGroIQr8eVKNwXkXPXHqB/7Pzbx1W79sLkW4aQfVLHw7ynH5WOrmOtyhGhQHVpyB1lHELU/+Kq9EImrSHVsMsZhk3ypeGxbTn0mJwaFV2XaSOlaLl2BibN4NJl1bo25OAplIE6LQmALcbARj8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=lB8gkU2F; arc=none smtp.client-ip=192.198.163.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="lB8gkU2F" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1753367109; x=1784903109; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=15ZHWHaWRSiwY6M4f3gJGxIPd+lGYskyqPDvKluQqrs=; b=lB8gkU2FHwcDLvT1tGbRtNHfw8kIvY1xEb8XiUNZmklzNWxDdLcbvx+u z16EK8g67XrcPRQnsDNz5Iah7DAugWERPaPo1zzdFkceJ8CInIkq0sBw3 XshrbyazErvyMkfqZNHP870SFkrf3gM2aYbofC3wIoaeKKVbKOc0vKj2/ pIZl2odRiMjsQ8FCtChRibIMDZDiS2OnVDN1dvnmN+/HSMFe5VvHuc3OP LKoj1/+a4eWx2WfU6HqMDbhIOekVqLIvcgNrvszcD9DHqoqWMHK56LWgZ /j1yUH/tg2bMtwteCOOdGdCsocMl4In0QvNsdbggcFlxGMyovd6wSpDLT w==; X-CSE-ConnectionGUID: YyYr5DQvS7GDcv01rjfumw== X-CSE-MsgGUID: iwkuu8v7QUuo5Ovowo6OMQ== X-IronPort-AV: E=McAfee;i="6800,10657,11501"; a="66250230" X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="66250230" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:09 -0700 X-CSE-ConnectionGUID: gElxmOdPQjK7VQylqlsuWg== X-CSE-MsgGUID: t3neb0kcTNaxww2WsG9ELg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="160245690" Received: from fdefranc-mobl3.ger.corp.intel.com (HELO fdefranc-mobl3.intel.com) ([10.245.246.151]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:04 -0700 From: "Fabio M. De Francesco" To: linux-cxl@vger.kernel.org Cc: Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Dan Williams , Robert Richter , ming.li@zohomail.com, linux-kernel@vger.kernel.org, "Fabio M. De Francesco" Subject: [PATCH 1/4 v4] cxl/core: Change match_*_by_range() signatures Date: Thu, 24 Jul 2025 16:20:31 +0200 Message-ID: <20250724142144.776992-2-fabio.m.de.francesco@linux.intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> References: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace struct range parameter with struct cxl_endpoint_decoder of which range is a member in the match_*_by_range() functions and rename them according to their semantics. This is in preparation for expanding these helpers to perform arch specific Root Decoders and Region matchings with cxl_endpoint_decoder(s). Cc: Alison Schofield Cc: Dan Williams Cc: Dave Jiang Cc: Ira Weiny Signed-off-by: Fabio M. De Francesco Reviewed-by: Jonathan Cameron --- drivers/cxl/core/region.c | 60 +++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index 6e5e1460068d..f607e7f97184 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -1759,27 +1759,29 @@ static int cmp_interleave_pos(const void *a, const = void *b) return cxled_a->pos - cxled_b->pos; } =20 -static int match_switch_decoder_by_range(struct device *dev, - const void *data) +static int match_switch_and_ep_decoders(struct device *dev, const void *da= ta) { + const struct cxl_endpoint_decoder *cxled =3D data; struct cxl_switch_decoder *cxlsd; - const struct range *r1, *r2 =3D data; - + const struct range *r1, *r2; =20 if (!is_switch_decoder(dev)) return 0; =20 cxlsd =3D to_cxl_switch_decoder(dev); r1 =3D &cxlsd->cxld.hpa_range; + r2 =3D &cxled->cxld.hpa_range; =20 if (is_root_decoder(dev)) return range_contains(r1, r2); return (r1->start =3D=3D r2->start && r1->end =3D=3D r2->end); } =20 -static int find_pos_and_ways(struct cxl_port *port, struct range *range, - int *pos, int *ways) +static int find_pos_and_ways(struct cxl_port *port, + struct cxl_endpoint_decoder *cxled, int *pos, + int *ways) { + struct range *range =3D &cxled->cxld.hpa_range; struct cxl_switch_decoder *cxlsd; struct cxl_port *parent; struct device *dev; @@ -1789,8 +1791,8 @@ static int find_pos_and_ways(struct cxl_port *port, s= truct range *range, if (!parent) return rc; =20 - dev =3D device_find_child(&parent->dev, range, - match_switch_decoder_by_range); + dev =3D device_find_child(&parent->dev, cxled, + match_switch_and_ep_decoders); if (!dev) { dev_err(port->uport_dev, "failed to find decoder mapping %#llx-%#llx\n", @@ -1876,7 +1878,7 @@ static int cxl_calc_interleave_pos(struct cxl_endpoin= t_decoder *cxled) if (is_cxl_root(iter)) break; =20 - rc =3D find_pos_and_ways(iter, range, &parent_pos, &parent_ways); + rc =3D find_pos_and_ways(iter, cxled, &parent_pos, &parent_ways); if (rc) return rc; =20 @@ -3215,24 +3217,28 @@ static int devm_cxl_add_dax_region(struct cxl_regio= n *cxlr) return rc; } =20 -static int match_decoder_by_range(struct device *dev, const void *data) +static int match_root_and_ep_decoders(struct device *dev, const void *data) { - const struct range *r1, *r2 =3D data; - struct cxl_decoder *cxld; + const struct cxl_endpoint_decoder *cxled =3D data; + const struct range *r1, *r2; + struct cxl_root_decoder *cxlrd; =20 - if (!is_switch_decoder(dev)) + if (!is_root_decoder(dev)) return 0; =20 - cxld =3D to_cxl_decoder(dev); - r1 =3D &cxld->hpa_range; + cxlrd =3D to_cxl_root_decoder(dev); + r1 =3D &cxlrd->cxlsd.cxld.hpa_range; + r2 =3D &cxled->cxld.hpa_range; + return range_contains(r1, r2); } =20 static struct cxl_decoder * -cxl_port_find_switch_decoder(struct cxl_port *port, struct range *hpa) +cxl_port_find_root_decoder(struct cxl_port *port, + struct cxl_endpoint_decoder *cxled) { - struct device *cxld_dev =3D device_find_child(&port->dev, hpa, - match_decoder_by_range); + struct device *cxld_dev =3D device_find_child(&port->dev, cxled, + match_root_and_ep_decoders); =20 return cxld_dev ? to_cxl_decoder(cxld_dev) : NULL; } @@ -3244,9 +3250,8 @@ cxl_find_root_decoder(struct cxl_endpoint_decoder *cx= led) struct cxl_port *port =3D cxled_to_port(cxled); struct cxl_root *cxl_root __free(put_cxl_root) =3D find_cxl_root(port); struct cxl_decoder *root, *cxld =3D &cxled->cxld; - struct range *hpa =3D &cxld->hpa_range; =20 - root =3D cxl_port_find_switch_decoder(&cxl_root->port, hpa); + root =3D cxl_port_find_root_decoder(&cxl_root->port, cxled); if (!root) { dev_err(cxlmd->dev.parent, "%s:%s no CXL window for range %#llx:%#llx\n", @@ -3258,11 +3263,12 @@ cxl_find_root_decoder(struct cxl_endpoint_decoder *= cxled) return to_cxl_root_decoder(&root->dev); } =20 -static int match_region_by_range(struct device *dev, const void *data) +static int match_region_and_ep_decoder(struct device *dev, const void *dat= a) { + const struct cxl_endpoint_decoder *cxled =3D data; + const struct range *r =3D &cxled->cxld.hpa_range; struct cxl_region_params *p; struct cxl_region *cxlr; - const struct range *r =3D data; =20 if (!is_cxl_region(dev)) return 0; @@ -3425,12 +3431,13 @@ static struct cxl_region *construct_region(struct c= xl_root_decoder *cxlrd, } =20 static struct cxl_region * -cxl_find_region_by_range(struct cxl_root_decoder *cxlrd, struct range *hpa) +cxl_find_region_by_range(struct cxl_root_decoder *cxlrd, + struct cxl_endpoint_decoder *cxled) { struct device *region_dev; =20 - region_dev =3D device_find_child(&cxlrd->cxlsd.cxld.dev, hpa, - match_region_by_range); + region_dev =3D device_find_child(&cxlrd->cxlsd.cxld.dev, cxled, + match_region_and_ep_decoder); if (!region_dev) return NULL; =20 @@ -3439,7 +3446,6 @@ cxl_find_region_by_range(struct cxl_root_decoder *cxl= rd, struct range *hpa) =20 int cxl_add_to_region(struct cxl_endpoint_decoder *cxled) { - struct range *hpa =3D &cxled->cxld.hpa_range; struct cxl_region_params *p; bool attach =3D false; int rc; @@ -3455,7 +3461,7 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cx= led) */ mutex_lock(&cxlrd->range_lock); struct cxl_region *cxlr __free(put_cxl_region) =3D - cxl_find_region_by_range(cxlrd, hpa); + cxl_find_region_by_range(cxlrd, cxled); if (!cxlr) cxlr =3D construct_region(cxlrd, cxled); mutex_unlock(&cxlrd->range_lock); --=20 2.50.1 From nobody Mon Oct 6 04:57:12 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 DBB5E2E5414; Thu, 24 Jul 2025 14:25:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367116; cv=none; b=iodsUcTpf6nAS/lTk6r9OZPh/g7y1lPYFy5nJ098BZN3sdsius2F4gr/smE6PjLIxmAG4h6zTXJ0Nq/mZWCT+suMBjFr3mN0D8WQ+Rl6ONLS6SfFpND/1Kxzb8suR9Y3j+fkBqYM1v6cx6n/UUr34meR+ozkG/28I4/Ov4VnzeE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367116; c=relaxed/simple; bh=5M5cMMIyVxTIneCLOuvT2muZq9GBRryiuEAUCSI2UD4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JCy/ipHl1lSnPhFrIVZmK7eMqkIHLQOLNunx5Ax2khcSwaIu/Dfh3gQkjsgGDz0RnrhWE9bDIPvf4YO/0xC9768sVi8WU8heTJ7IsJeIyLQfHOZNQ78OdbqAZ6iUJ7FHFDmtxRRlUt1jsT22dP6zSSqnGWdjLwAESxwURJj8Z4Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=KblPWyzL; arc=none smtp.client-ip=192.198.163.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="KblPWyzL" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1753367115; x=1784903115; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5M5cMMIyVxTIneCLOuvT2muZq9GBRryiuEAUCSI2UD4=; b=KblPWyzLr8EcKaIo0VbvdMyHtiApNUFf1/GKAPLMZ4Qsfz/qaVA0QKaH 646kR6k5TdyL/hE8xkBFSVFg9Ga0+vZY6A7jjgWNcs0NF6iTUkD4QR2gA uC/HQyj3jS9M6TRY4RMD5FtcG5c6VhtKbIYOwbEFqPaPXYEAXyV4TFF+q BzcC4S6J4QXm5E6vjZppgpqO9nlp42oG2zcEUxFFanzH2p6/uQEbg5Edc VDd2f+pkbdWoQUlF6SAWS7rREsOOxgBqvzwfUKmN62dD/uvIbEfNzOGQo JAL+KI1y6DgwwBwR837G+6Sq3NzA83Vql8Uhveu8c/6Uja7dUFqv0PoTI A==; X-CSE-ConnectionGUID: ArE7QaDYRYmGpW0D4qtq6g== X-CSE-MsgGUID: 9g7iVLBwThOY7VAlS6Xx/g== X-IronPort-AV: E=McAfee;i="6800,10657,11501"; a="66250252" X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="66250252" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:14 -0700 X-CSE-ConnectionGUID: d+k6iEqBR8ypi2bGg3sprw== X-CSE-MsgGUID: wCPW4++JSSeYD7Kj1LBqQw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="160245718" Received: from fdefranc-mobl3.ger.corp.intel.com (HELO fdefranc-mobl3.intel.com) ([10.245.246.151]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:10 -0700 From: "Fabio M. De Francesco" To: linux-cxl@vger.kernel.org Cc: Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Dan Williams , Robert Richter , ming.li@zohomail.com, linux-kernel@vger.kernel.org, "Fabio M. De Francesco" Subject: [PATCH 2/4 v4] cxl/core: Add helpers to detect Low Memory Holes on x86 Date: Thu, 24 Jul 2025 16:20:32 +0200 Message-ID: <20250724142144.776992-3-fabio.m.de.francesco@linux.intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> References: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In x86 with Low memory Hole, the BIOS may publishes CFMWS that describe SPA ranges which are subsets of the corresponding CXL Endpoint Decoders HPA's because the CFMWS never intersects LMH's while EP Decoders HPA's ranges are always guaranteed to align to the NIW * 256M rule. In order to construct Regions and attach Decoders, the driver needs to match Root Decoders and Regions with Endpoint Decoders, but it fails and the entire process returns errors because it doesn't expect to deal with SPA range lengths smaller than corresponding HPA's. Introduce functions that indirectly detect x86 LMH's by comparing SPA's with corresponding HPA's. They will be used in the process of Regions creation and Endpoint attachments to prevent driver failures in a few steps of the above-mentioned process. The helpers return true when HPA/SPA misalignments are detected under specific conditions: both the SPA and HPA ranges must start at LMH_CFMWS_RANGE_START (that in x86 with LMH's is 0x0), SPA range sizes be less than HPA's, SPA's range's size be less than 4G, HPA's size be aligned to the NIW * 256M rule. Also introduce a function to adjust the range end of the Regions to be created on x86 with LMH's. Cc: Alison Schofield Cc: Dan Williams Cc: Dave Jiang Cc: Ira Weiny Signed-off-by: Fabio M. De Francesco --- drivers/cxl/Kconfig | 5 +++ drivers/cxl/core/Makefile | 1 + drivers/cxl/core/platform.c | 85 +++++++++++++++++++++++++++++++++++++ drivers/cxl/core/platform.h | 32 ++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 drivers/cxl/core/platform.c create mode 100644 drivers/cxl/core/platform.h diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index 48b7314afdb8..eca90baeac10 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig @@ -211,6 +211,11 @@ config CXL_REGION =20 If unsure say 'y' =20 +config CXL_PLATFORM_QUIRKS + def_bool y + depends on CXL_REGION + depends on X86 + config CXL_REGION_INVALIDATION_TEST bool "CXL: Region Cache Management Bypass (TEST)" depends on CXL_REGION diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index 79e2ef81fde8..4be729fb7d64 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile @@ -18,6 +18,7 @@ cxl_core-y +=3D ras.o cxl_core-y +=3D acpi.o cxl_core-$(CONFIG_TRACING) +=3D trace.o cxl_core-$(CONFIG_CXL_REGION) +=3D region.o +cxl_core-$(CONFIG_CXL_PLATFORM_QUIRKS) +=3D platform.o cxl_core-$(CONFIG_CXL_MCE) +=3D mce.o cxl_core-$(CONFIG_CXL_FEATURES) +=3D features.o cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) +=3D edac.o diff --git a/drivers/cxl/core/platform.c b/drivers/cxl/core/platform.c new file mode 100644 index 000000000000..8202750742d0 --- /dev/null +++ b/drivers/cxl/core/platform.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "platform.h" +#include "cxlmem.h" +#include "core.h" + +/* Start of CFMWS range that end before x86 Low Memory Holes */ +#define LMH_CFMWS_RANGE_START 0x0ULL + +/* + * Match CXL Root and Endpoint Decoders by comparing SPA and HPA ranges. + * + * On x86, CFMWS ranges never intersect memory holes while endpoint decode= rs + * HPA range sizes are always guaranteed aligned to NIW * 256MB; therefore, + * the given endpoint decoder HPA range size is always expected aligned and + * also larger than that of the matching root decoder. If there are LMH's, + * the root decoder range end is always less than SZ_4G. + */ +bool platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, + const struct cxl_endpoint_decoder *cxled) +{ + const struct range *r1, *r2; + int niw; + + r1 =3D &cxlrd->cxlsd.cxld.hpa_range; + r2 =3D &cxled->cxld.hpa_range; + niw =3D cxled->cxld.interleave_ways; + + if (r1->start =3D=3D LMH_CFMWS_RANGE_START && r1->start =3D=3D r2->start = && + r1->end < (LMH_CFMWS_RANGE_START + SZ_4G) && r1->end < r2->end && + IS_ALIGNED(range_len(r2), niw * SZ_256M)) + return true; + + return false; +} + +/* + * Similar to platform_root_decoder_contains(), it matches regions and + * decoders + */ +bool platform_region_contains(const struct cxl_region_params *p, + const struct cxl_decoder *cxld) +{ + const struct range *r =3D &cxld->hpa_range; + const struct resource *res =3D p->res; + int niw =3D cxld->interleave_ways; + + if (res->start =3D=3D LMH_CFMWS_RANGE_START && res->start =3D=3D r->start= && + res->end < (LMH_CFMWS_RANGE_START + SZ_4G) && res->end < r->end && + IS_ALIGNED(range_len(r), niw * SZ_256M)) + return true; + + return false; +} + +void platform_res_adjust(struct resource *res, + struct cxl_endpoint_decoder *cxled, + const struct cxl_root_decoder *cxlrd) +{ + if (!platform_root_decoder_contains(cxlrd, cxled)) + return; + + guard(rwsem_write)(&cxl_dpa_rwsem); + dev_info(cxled_to_memdev(cxled)->dev.parent, + "(LMH) Resources were (%s: %pr, %pr)\n", + dev_name(&cxled->cxld.dev), res, cxled->dpa_res); + if (res) { + /* + * A region must be constructed with Endpoint Decoder's + * HPA range end adjusted to Root Decoder's resource end + */ + res->end =3D cxlrd->res->end; + } + /* + * The Endpoint Decoder's dpa_res->end must be adjusted with Root + * Decoder's resource end + */ + cxled->dpa_res->end =3D + cxled->dpa_res->start + + resource_size(cxlrd->res) / cxled->cxld.interleave_ways - 1; + dev_info(cxled_to_memdev(cxled)->dev.parent, + "(LMH) Resources have been adjusted (%s: %pr, %pr)\n", + dev_name(&cxled->cxld.dev), res, cxled->dpa_res); +} diff --git a/drivers/cxl/core/platform.h b/drivers/cxl/core/platform.h new file mode 100644 index 000000000000..0baa39938729 --- /dev/null +++ b/drivers/cxl/core/platform.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "cxl.h" + +#ifdef CONFIG_CXL_PLATFORM_QUIRKS +bool platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, + const struct cxl_endpoint_decoder *cxled); +bool platform_region_contains(const struct cxl_region_params *p, + const struct cxl_decoder *cxld); +void platform_res_adjust(struct resource *res, + struct cxl_endpoint_decoder *cxled, + const struct cxl_root_decoder *cxlrd); +#else +static bool +platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, + const struct cxl_endpoint_decoder *cxled) +{ + return false; +} + +static bool platform_region_contains(const struct cxl_region_params *p, + const struct cxl_decoder *cxld) +{ + return false; +} + +void platform_res_adjust(struct resource *res, + struct cxl_endpoint_decoder *cxled, + const struct cxl_root_decoder *cxlrd) +{ +} +#endif /* CONFIG_CXL_PLATFORM_QUIRKS */ --=20 2.50.1 From nobody Mon Oct 6 04:57:12 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 872EC2E040A; Thu, 24 Jul 2025 14:25:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367125; cv=none; b=N8dIxlrZPXESrJuJl1QCZusNdZcm4+ejmkbE8KnHR6AyJSsMFvmYysS1hBiZV7rjPJuj8fHwfRRSA6094+2OfZc9XepQ1dsccSFPPQN6HPikNYymGNgmcaGDnszYHqgjcgSTXpE82eSOKvswgW5BrnpPP4WzdVWkAIxe9GfAiT0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367125; c=relaxed/simple; bh=cgmwb3mci90b/IZ5B6grKyUsc+NSsc/OSjiBfPuIC/E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YXqftFKr9i2utdA8EG1EwFzGhib+i/yBRFGXon7axMollGZbUv3vzX7ZXCiUIGKbR/kvSonj6H3qEi3YA4MMjacEFtTo5HEedisMwS8FSe/gVjxZx31lbtELF/nZhJsDIxJ+0lbVEEFPuhfpasCGaHemJNfEzeG0PrZptXwfN5Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SvafLgFI; arc=none smtp.client-ip=192.198.163.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SvafLgFI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1753367123; x=1784903123; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cgmwb3mci90b/IZ5B6grKyUsc+NSsc/OSjiBfPuIC/E=; b=SvafLgFIf6aKWVfwgHKXxPiDCfayarBNb4KMIeT/8M/5GnTEMhEXlun4 2G7dAfm74FnQRNCB7GN4YrgS6cd1rHZvKWh3v63/YBJBYBDC0EoBw0ex+ UJYyEMYP93nlkpi9j3ThCelR4gRZhlPcoHqi9vwFEWBcNlvhMbk453PES Q4/Qgo1UP1TRqEVB6x40k3PTL8SIBJhazdrQzxvzP8ndW+jyzkn3ghwEu fGxCDqgYBTKm5vQxJx/fdOx1qZNQC2aqVpUnwcYiNtjyB9LAMkkWUHhWQ jOjPTotng85jlx3ALCM99Haj6InVrl4uAEOsgPy6MTzx5dgRytnhM9DT2 A==; X-CSE-ConnectionGUID: +xVY3sBFSPi+w8F9aKnWNA== X-CSE-MsgGUID: IiUPlW6/SrOlHhR+PPlkdA== X-IronPort-AV: E=McAfee;i="6800,10657,11501"; a="66250265" X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="66250265" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:22 -0700 X-CSE-ConnectionGUID: Hu4B2kGKSaK7k1wfKFL3sQ== X-CSE-MsgGUID: 85cqgE+BSmmr131X98nlhQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="160245764" Received: from fdefranc-mobl3.ger.corp.intel.com (HELO fdefranc-mobl3.intel.com) ([10.245.246.151]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:18 -0700 From: "Fabio M. De Francesco" To: linux-cxl@vger.kernel.org Cc: Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Dan Williams , Robert Richter , ming.li@zohomail.com, linux-kernel@vger.kernel.org, "Fabio M. De Francesco" Subject: [PATCH 3/4 v4] cxl/core: Enable Region creation on x86 with LMH Date: Thu, 24 Jul 2025 16:20:33 +0200 Message-ID: <20250724142144.776992-4-fabio.m.de.francesco@linux.intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> References: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The CXL Fixed Memory Window Structure (CFMWS) describes zero or more Host Physical Address (HPA) windows that are associated with each CXL Host Bridge. Each window represents a contiguous HPA that may be interleaved with one or more targets (CXL v3.1 - 9.18.1.3). The Low Memory Hole (LMH) of x86 is a range of addresses of physical low memory to which systems cannot send transactions. In some cases the size of that hole is not compatible with the CXL hardware decoder constraint that the size is always aligned to 256M * Interleave Ways. On those systems, BIOS publishes CFMWS which communicate the active System Physical Address (SPA) ranges that map to a subset of the Host Physical Address (HPA) ranges. The SPA range trims out the hole, and capacity in the endpoint is lost with no SPA to map to CXL HPA in that hole. In the early stages of CXL Regions construction and attach on platforms with Low Memory Holes, cxl_add_to_region() fails and returns an error because it can't find any CXL Window that matches a given CXL Endpoint Decoder. Detect a Low Memory Hole by comparing Root Decoders and Endpoint Decoders ranges with the use of arch_match_{spa,region}() helpers. Match Root Decoders and CXL Regions with corresponding CXL Endpoint Decoders. Currently a Low Memory Holes would prevent the matching functions to return true. Construct CXL Regions with HPA range's end adjusted to the matching SPA. Allow the attach target process to complete by allowing Regions to not fit with alignment constraints (i.e., alignment to NIW * 256M rule). Cc: Alison Schofield Cc: Dan Williams Cc: Dave Jiang Cc: Ira Weiny Signed-off-by: Fabio M. De Francesco --- drivers/cxl/core/region.c | 53 +++++++++++++++++++++++++++++++++------ tools/testing/cxl/Kbuild | 1 + 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index f607e7f97184..b7fdf9c4393d 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -12,6 +12,7 @@ #include #include #include +#include "platform.h" #include "core.h" =20 /** @@ -834,6 +835,8 @@ static int match_free_decoder(struct device *dev, const= void *data) static bool region_res_match_cxl_range(const struct cxl_region_params *p, struct range *range) { + struct cxl_decoder *cxld; + if (!p->res) return false; =20 @@ -842,8 +845,15 @@ static bool region_res_match_cxl_range(const struct cx= l_region_params *p, * to be fronted by the DRAM range in current known implementation. * This assumption will be made until a variant implementation exists. */ - return p->res->start + p->cache_size =3D=3D range->start && - p->res->end =3D=3D range->end; + if (p->res->start + p->cache_size =3D=3D range->start && + p->res->end =3D=3D range->end) + return true; + + cxld =3D container_of(range, struct cxl_decoder, hpa_range); + if (platform_region_contains(p, cxld)) + return true; + + return false; } =20 static int match_auto_decoder(struct device *dev, const void *data) @@ -1763,6 +1773,7 @@ static int match_switch_and_ep_decoders(struct device= *dev, const void *data) { const struct cxl_endpoint_decoder *cxled =3D data; struct cxl_switch_decoder *cxlsd; + struct cxl_root_decoder *cxlrd; const struct range *r1, *r2; =20 if (!is_switch_decoder(dev)) @@ -1772,8 +1783,13 @@ static int match_switch_and_ep_decoders(struct devic= e *dev, const void *data) r1 =3D &cxlsd->cxld.hpa_range; r2 =3D &cxled->cxld.hpa_range; =20 - if (is_root_decoder(dev)) - return range_contains(r1, r2); + if (is_root_decoder(dev)) { + if (range_contains(r1, r2)) + return 1; + cxlrd =3D to_cxl_root_decoder(dev); + if (platform_root_decoder_contains(cxlrd, cxled)) + return 1; + } return (r1->start =3D=3D r2->start && r1->end =3D=3D r2->end); } =20 @@ -1990,7 +2006,7 @@ static int cxl_region_attach(struct cxl_region *cxlr, } =20 if (resource_size(cxled->dpa_res) * p->interleave_ways + p->cache_size != =3D - resource_size(p->res)) { + resource_size(p->res) && !platform_root_decoder_contains(cxlrd, cxled= )) { dev_dbg(&cxlr->dev, "%s:%s-size-%#llx * ways-%d + cache-%#llx !=3D region-size-%#llx\n", dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), @@ -3230,7 +3246,12 @@ static int match_root_and_ep_decoders(struct device = *dev, const void *data) r1 =3D &cxlrd->cxlsd.cxld.hpa_range; r2 =3D &cxled->cxld.hpa_range; =20 - return range_contains(r1, r2); + if (range_contains(r1, r2)) + return true; + if (platform_root_decoder_contains(cxlrd, cxled)) + return true; + + return false; } =20 static struct cxl_decoder * @@ -3277,8 +3298,12 @@ static int match_region_and_ep_decoder(struct device= *dev, const void *data) p =3D &cxlr->params; =20 guard(rwsem_read)(&cxl_region_rwsem); - if (p->res && p->res->start =3D=3D r->start && p->res->end =3D=3D r->end) - return 1; + if (p->res) { + if (p->res->start =3D=3D r->start && p->res->end =3D=3D r->end) + return 1; + if (platform_region_contains(p, &cxled->cxld)) + return 1; + } =20 return 0; } @@ -3355,6 +3380,12 @@ static int __construct_region(struct cxl_region *cxl= r, *res =3D DEFINE_RES_MEM_NAMED(hpa->start, range_len(hpa), dev_name(&cxlr->dev)); =20 + /* + * Trim the HPA retrieved from hardware to fit the SPA mapped by the + * platform + */ + platform_res_adjust(res, cxled, cxlrd); + rc =3D cxl_extended_linear_cache_resize(cxlr, res); if (rc && rc !=3D -EOPNOTSUPP) { /* @@ -3464,6 +3495,12 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *c= xled) cxl_find_region_by_range(cxlrd, cxled); if (!cxlr) cxlr =3D construct_region(cxlrd, cxled); + else + /* + * Adjust the Endpoint Decoder's dpa_res to fit the Region which + * it has to be attached to + */ + platform_res_adjust(NULL, cxled, cxlrd); mutex_unlock(&cxlrd->range_lock); =20 rc =3D PTR_ERR_OR_ZERO(cxlr); diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild index 31a2d73c963f..77e392c4b541 100644 --- a/tools/testing/cxl/Kbuild +++ b/tools/testing/cxl/Kbuild @@ -65,6 +65,7 @@ cxl_core-y +=3D $(CXL_CORE_SRC)/ras.o cxl_core-y +=3D $(CXL_CORE_SRC)/acpi.o cxl_core-$(CONFIG_TRACING) +=3D $(CXL_CORE_SRC)/trace.o cxl_core-$(CONFIG_CXL_REGION) +=3D $(CXL_CORE_SRC)/region.o +cxl_core-$(CONFIG_CXL_PLATFORM_QUIRKS) +=3D $(CXL_CORE_SRC)/platform.o cxl_core-$(CONFIG_CXL_MCE) +=3D $(CXL_CORE_SRC)/mce.o cxl_core-$(CONFIG_CXL_FEATURES) +=3D $(CXL_CORE_SRC)/features.o cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) +=3D $(CXL_CORE_SRC)/edac.o --=20 2.50.1 From nobody Mon Oct 6 04:57:12 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 659692E54B9; Thu, 24 Jul 2025 14:25:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367130; cv=none; b=alvpPTgR1/BMb1gvJJCqEa4cGlhM/chWJ7DlcvuSDZHvV/vIz9gmZH1/oqAS6/jSAv8rYpIqI8c5Le8yQLDzUL4GbxEGV8ndFIzl1fxWUt3HCJgQrPQyJKj422/wdGnZvPMtd9PFM6eJnotlEbTJcb6iPWSZqeomtcUFxRhI6dk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753367130; c=relaxed/simple; bh=EAPPpssxPZYF3VUgXA7gXTj4OzBpD/qHTIbo4501zOc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AkXeXldW3jVMAX5Npcdha30RY35RuY0lYX/AlM+tphhDX9tGKrrS4KhFdjMPiI+pnFu+7mIWf2HDXoNj8xMK2td3NLB2hHMKFsziGVdX9DvrmSWb1xa4tnhLlAFlF8IKvMzbuim+JbPJjG4WSE2X1DAxWmhvQORNyHU/HptexYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=OJtWciWC; arc=none smtp.client-ip=192.198.163.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OJtWciWC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1753367128; x=1784903128; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=EAPPpssxPZYF3VUgXA7gXTj4OzBpD/qHTIbo4501zOc=; b=OJtWciWCtWiSydbOhPnBa3nhv7h6gpB4Jq36WasLsPugTjtDZ3DCQnxq ssQJ8TcC7cm5vkS72kh+2z2yJHXIWvuvg+UYrQG8ZCVjexsAqtpX/gqpK +UYaZcO0WKKxjJ6ccXYyrCYVEIRsnrg2b8480VXAUo/pS4kDcXNcPdPew 1Ly1SWCvsWUxmDNqzgvF/rXBSo+Z71OPzjW9woENswqBR6mBrnN1ftnxh cCP8gJVYqCbJwTtLesHC9S43fCXncAj4HDcU+ok5Np1pOrQKxdzjkoSdS k7TGG3qPTGm7Evc0mkqFIAcR8XmYRv056kdpGJ9qywn1IjL+9IedHPi/O w==; X-CSE-ConnectionGUID: dIjFLyVlQvq19ipq+K4GKg== X-CSE-MsgGUID: aaR+PiLzQ6uZv6wtTFF3hA== X-IronPort-AV: E=McAfee;i="6800,10657,11501"; a="66250287" X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="66250287" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:28 -0700 X-CSE-ConnectionGUID: V49M8n9iSAacmvlh6IrDVg== X-CSE-MsgGUID: DTLVz4BWSqGScTPqJso6HA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,337,1744095600"; d="scan'208";a="160245802" Received: from fdefranc-mobl3.ger.corp.intel.com (HELO fdefranc-mobl3.intel.com) ([10.245.246.151]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2025 07:25:24 -0700 From: "Fabio M. De Francesco" To: linux-cxl@vger.kernel.org Cc: Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Dan Williams , Robert Richter , ming.li@zohomail.com, linux-kernel@vger.kernel.org, "Fabio M. De Francesco" Subject: [PATCH 4/4 v4] cxl/test: Simulate an x86 Low Memory Hole for tests Date: Thu, 24 Jul 2025 16:20:34 +0200 Message-ID: <20250724142144.776992-5-fabio.m.de.francesco@linux.intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> References: <20250724142144.776992-1-fabio.m.de.francesco@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Simulate an x86 Low Memory Hole for the CXL tests by changing the first mock CFMWS range size to 768MB and the CXL Endpoint Decoder HPA range sizes to 1GB. The auto-created region of cxl-test uses mock_cfmws[0], therefore the LMH path in the CXL Driver will be exercised every time the cxl-test module is loaded. Executing unit test: cxl-topology.sh, confirms the region created successfully with a LMH. Since mock_cfmws[0] range base address is typically different from the one published by the BIOS on real hardware, the driver would fail to create and attach CXL Regions when it's run on the mock environment created by cxl-tests. Therefore, save the mock_cfmsw[0] range base_hpa and reuse it to match CXL Root Decoders and Regions with Endpoint Decoders when the driver is run on mock devices. Cc: Alison Schofield Cc: Dan Williams Cc: Dave Jiang Cc: Ira Weiny Signed-off-by: Fabio M. De Francesco --- drivers/cxl/core/platform.c | 9 +- tools/testing/cxl/Kbuild | 1 + tools/testing/cxl/mock_platform.c | 137 ++++++++++++++++++++++++++++++ tools/testing/cxl/test/cxl.c | 10 +++ tools/testing/cxl/test/mock.h | 1 + 5 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 tools/testing/cxl/mock_platform.c diff --git a/drivers/cxl/core/platform.c b/drivers/cxl/core/platform.c index 8202750742d0..ba1dafece495 100644 --- a/drivers/cxl/core/platform.c +++ b/drivers/cxl/core/platform.c @@ -17,8 +17,9 @@ * also larger than that of the matching root decoder. If there are LMH's, * the root decoder range end is always less than SZ_4G. */ -bool platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, - const struct cxl_endpoint_decoder *cxled) +__weak bool +platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, + const struct cxl_endpoint_decoder *cxled) { const struct range *r1, *r2; int niw; @@ -39,8 +40,8 @@ bool platform_root_decoder_contains(const struct cxl_root= _decoder *cxlrd, * Similar to platform_root_decoder_contains(), it matches regions and * decoders */ -bool platform_region_contains(const struct cxl_region_params *p, - const struct cxl_decoder *cxld) +__weak bool platform_region_contains(const struct cxl_region_params *p, + const struct cxl_decoder *cxld) { const struct range *r =3D &cxld->hpa_range; const struct resource *res =3D p->res; diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild index 77e392c4b541..64c5c8c34805 100644 --- a/tools/testing/cxl/Kbuild +++ b/tools/testing/cxl/Kbuild @@ -66,6 +66,7 @@ cxl_core-y +=3D $(CXL_CORE_SRC)/acpi.o cxl_core-$(CONFIG_TRACING) +=3D $(CXL_CORE_SRC)/trace.o cxl_core-$(CONFIG_CXL_REGION) +=3D $(CXL_CORE_SRC)/region.o cxl_core-$(CONFIG_CXL_PLATFORM_QUIRKS) +=3D $(CXL_CORE_SRC)/platform.o +cxl_core-$(CONFIG_CXL_PLATFORM_QUIRKS) +=3D mock_platform.o cxl_core-$(CONFIG_CXL_MCE) +=3D $(CXL_CORE_SRC)/mce.o cxl_core-$(CONFIG_CXL_FEATURES) +=3D $(CXL_CORE_SRC)/features.o cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) +=3D $(CXL_CORE_SRC)/edac.o diff --git a/tools/testing/cxl/mock_platform.c b/tools/testing/cxl/mock_pla= tform.c new file mode 100644 index 000000000000..1775c64b3c7c --- /dev/null +++ b/tools/testing/cxl/mock_platform.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include + +#include +#include +#include "test/mock.h" + +static u64 mock_cfmws0_range_start; + +void set_mock_cfmws0_range_start(u64 start) +{ + mock_cfmws0_range_start =3D start; +} +EXPORT_SYMBOL_NS_GPL(set_mock_cfmws0_range_start, "CXL"); + +static bool is_mock_port(struct device *dev) +{ + struct cxl_mock_ops *(*get_ops_fn)(int *index); + struct cxl_mock_ops *ops =3D NULL; + void (*put_ops_fn)(int index); + bool is_mock =3D false; + int index; + + get_ops_fn =3D symbol_get(get_cxl_mock_ops); + if (!get_ops_fn) + return false; + put_ops_fn =3D symbol_get(put_cxl_mock_ops); + if (!put_ops_fn) + goto out; + + ops =3D get_ops_fn(&index); + if (ops) + is_mock =3D ops->is_mock_port(dev); + put_ops_fn(index); + +out: + symbol_put(get_cxl_mock_ops); + + return is_mock; +} + +/* Start of CFMWS range that end before x86 Low Memory Holes */ +#define LMH_CFMWS_RANGE_START 0x0ULL + +static bool +real_platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, + const struct cxl_endpoint_decoder *cxled) +{ + const struct range *r1, *r2; + int niw; + + r1 =3D &cxlrd->cxlsd.cxld.hpa_range; + r2 =3D &cxled->cxld.hpa_range; + niw =3D cxled->cxld.interleave_ways; + + if (r1->start =3D=3D LMH_CFMWS_RANGE_START && r1->start =3D=3D r2->start = && + r1->end < (LMH_CFMWS_RANGE_START + SZ_4G) && r1->end < r2->end && + IS_ALIGNED(range_len(r2), niw * SZ_256M)) + return true; + + return false; +} + +static bool +cxl_test_platform_root_decoder_contains(const struct cxl_root_decoder *cxl= rd, + const struct cxl_endpoint_decoder *cxled) +{ + const struct range *r1, *r2; + int niw; + + r1 =3D &cxlrd->cxlsd.cxld.hpa_range; + r2 =3D &cxled->cxld.hpa_range; + niw =3D cxled->cxld.interleave_ways; + + if (r1->start =3D=3D mock_cfmws0_range_start && r1->start =3D=3D r2->star= t && + r1->end < (mock_cfmws0_range_start + SZ_4G) && r1->end < r2->end && + IS_ALIGNED(range_len(r2), niw * SZ_256M)) + return true; + + return false; +} + +bool platform_root_decoder_contains(const struct cxl_root_decoder *cxlrd, + const struct cxl_endpoint_decoder *cxled) +{ + struct cxl_port *port =3D to_cxl_port(cxled->cxld.dev.parent); + + if (is_mock_port(port->uport_dev)) + return cxl_test_platform_root_decoder_contains(cxlrd, cxled); + + return real_platform_root_decoder_contains(cxlrd, cxled); +} + +static bool real_platform_region_contains(const struct cxl_region_params *= p, + const struct cxl_decoder *cxld) +{ + const struct range *r =3D &cxld->hpa_range; + const struct resource *res =3D p->res; + int niw =3D cxld->interleave_ways; + + if (res->start =3D=3D LMH_CFMWS_RANGE_START && res->start =3D=3D r->start= && + res->end < (LMH_CFMWS_RANGE_START + SZ_4G) && res->end < r->end && + IS_ALIGNED(range_len(r), niw * SZ_256M)) + return true; + + return false; +} + +static bool cxl_test_platform_region_contains(const struct cxl_region_para= ms *p, + const struct cxl_decoder *cxld) +{ + const struct range *r =3D &cxld->hpa_range; + const struct resource *res =3D p->res; + int niw =3D cxld->interleave_ways; + + if (res->start =3D=3D mock_cfmws0_range_start && res->start =3D=3D r->sta= rt && + res->end < (mock_cfmws0_range_start + SZ_4G) && res->end < r->end && + IS_ALIGNED(range_len(r), niw * SZ_256M)) + return true; + + return false; +} + +bool platform_region_contains(const struct cxl_region_params *p, + const struct cxl_decoder *cxld) +{ + struct cxl_port *port =3D to_cxl_port(cxld->dev.parent); + + if (is_mock_port(port->uport_dev)) + return cxl_test_platform_region_contains(p, cxld); + + return real_platform_region_contains(p, cxld); +} diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c index 8a5815ca870d..a411c055d390 100644 --- a/tools/testing/cxl/test/cxl.c +++ b/tools/testing/cxl/test/cxl.c @@ -212,7 +212,11 @@ static struct { .restrictions =3D ACPI_CEDT_CFMWS_RESTRICT_TYPE3 | ACPI_CEDT_CFMWS_RESTRICT_VOLATILE, .qtg_id =3D FAKE_QTG_ID, +#if defined(CONFIG_CXL_PLATFORM_QUIRKS) + .window_size =3D SZ_256M * 3UL, +#else .window_size =3D SZ_256M * 4UL, +#endif }, .target =3D { 0 }, }, @@ -453,6 +457,8 @@ static int populate_cedt(void) if (!res) return -ENOMEM; window->base_hpa =3D res->range.start; + if (i =3D=3D 0) + set_mock_cfmws0_range_start(res->range.start); } =20 return 0; @@ -744,7 +750,11 @@ static void mock_init_hdm_decoder(struct cxl_decoder *= cxld) struct cxl_endpoint_decoder *cxled; struct cxl_switch_decoder *cxlsd; struct cxl_port *port, *iter; +#if defined(CONFIG_CXL_PLATFORM_QUIRKS) + const int size =3D SZ_1G; +#else const int size =3D SZ_512M; +#endif struct cxl_memdev *cxlmd; struct cxl_dport *dport; struct device *dev; diff --git a/tools/testing/cxl/test/mock.h b/tools/testing/cxl/test/mock.h index d1b0271d2822..792eabbd0f18 100644 --- a/tools/testing/cxl/test/mock.h +++ b/tools/testing/cxl/test/mock.h @@ -32,3 +32,4 @@ void register_cxl_mock_ops(struct cxl_mock_ops *ops); void unregister_cxl_mock_ops(struct cxl_mock_ops *ops); struct cxl_mock_ops *get_cxl_mock_ops(int *index); void put_cxl_mock_ops(int index); +void set_mock_cfmws0_range_start(u64 start); --=20 2.50.1