lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 21 Jun 2022 13:56:40 -0700
From:   Dan Williams <dan.j.williams@...el.com>
To:     Davidlohr Bueso <dave@...olabs.net>, <linux-cxl@...r.kernel.org>
CC:     <dan.j.williams@...el.com>, <alison.schofield@...el.com>,
        <bwidawsk@...nel.org>, <ira.weiny@...el.com>,
        <vishal.l.verma@...el.com>, <a.manzanares@...sung.com>,
        <dave@...olabs.net>, <linux-kernel@...r.kernel.org>
Subject: RE: [PATCH] cxl/acpi: Verify CHBS consistency

Davidlohr Bueso wrote:
> Similarly to verifying the cfwms, have a cxl_acpi_chbs_verify(),
> as described by the CXL T3 Memory Device Software Guide
> for CXL 2.0 platforms.
> 
> Also while at it, tuck the rc check for nvdimm bridge into
> the pmem branch.
> 
> Signed-off-by: Davidlohr Bueso <dave@...olabs.net>
> ---
> 
>  drivers/cxl/acpi.c | 64 +++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> index 40286f5df812..33b5f362c9f1 100644
> --- a/drivers/cxl/acpi.c
> +++ b/drivers/cxl/acpi.c
> @@ -187,14 +187,65 @@ static int add_host_bridge_uport(struct device *match, void *arg)
>  struct cxl_chbs_context {
>  	struct device *dev;
>  	unsigned long long uid;
> +	struct cxl_port *root_port;
>  	resource_size_t chbcr;
>  };
>  
> +static inline bool range_overlaps(struct range *r1, struct range *r2)
> +{
> +	return r1->start <= r2->end && r2->start <= r1->end;
> +}
> +
> +static int cxl_acpi_chbs_verify(struct cxl_chbs_context *cxt,
> +				struct acpi_cedt_chbs *chbs)
> +{
> +	struct device *dev = cxt->dev;
> +	struct cxl_dport *dport;
> +	struct cxl_port *root_port = cxt->root_port;
> +	struct range chbs_range = {
> +		.start = chbs->base,
> +		.end = chbs->base + chbs->length - 1,
> +	};
> +
> +	if (chbs->cxl_version > 1) {
> +		dev_err(dev, "CHBS Unsupported CXL Version\n");
> +		return -EINVAL;
> +	}
> +
> +	if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11)
> +		return 0;
> +
> +	if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL20 &&
> +	    (chbs->length != ACPI_CEDT_CHBS_LENGTH_CXL20)) {
> +		dev_err(dev, "Platform does not support CXL 2.0\n");
> +		return -EINVAL;
> +	}
> +
> +	device_lock(&root_port->dev);
> +	list_for_each_entry(dport, &root_port->dports, list) {
> +		struct range dport_range = {
> +			.start = dport->component_reg_phys,
> +			.end = dport->component_reg_phys +
> +			CXL_COMPONENT_REG_BLOCK_SIZE - 1,
> +		};
> +
> +		if (range_overlaps(&chbs_range, &dport_range)) {
> +			device_unlock(&root_port->dev);
> +			dev_err(dev, "CHBS overlapping Base and Length pair\n");
> +			return -EINVAL;
> +		}

For cxl_port objects this happens "for free" as a side effect of the:

        crb = devm_cxl_iomap_block(dev, port->component_reg_phys,
                                   CXL_COMPONENT_REG_BLOCK_SIZE);

...call in devm_cxl_setup_hdm(), where it tries to exclusively claim the
component register block for that cxl_port driver instance.

I.e. if the CHBS provides overlapping / duplicated ranges the failure is
localized to the cxl_port_probe() event for that port, and can be
debugged further by disabling one of the conflicts.

> +	}
> +	device_unlock(&root_port->dev);
> +
> +	return 0;
> +}
> +
>  static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
>  			 const unsigned long end)
>  {
>  	struct cxl_chbs_context *ctx = arg;
>  	struct acpi_cedt_chbs *chbs;
> +	int ret;
>  
>  	if (ctx->chbcr)
>  		return 0;
> @@ -203,6 +254,11 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
>  
>  	if (ctx->uid != chbs->uid)
>  		return 0;
> +
> +	ret = cxl_acpi_chbs_verify(ctx, chbs);
> +	if (ret)
> +		return ret;
> +
>  	ctx->chbcr = chbs->base;
>  
>  	return 0;
> @@ -232,6 +288,7 @@ static int add_host_bridge_dport(struct device *match, void *arg)
>  	ctx = (struct cxl_chbs_context) {
>  		.dev = host,
>  		.uid = uid,
> +		.root_port = root_port,
>  	};
>  	acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx);
>  
> @@ -321,11 +378,12 @@ static int cxl_acpi_probe(struct platform_device *pdev)
>  	if (rc < 0)
>  		return rc;
>  
> -	if (IS_ENABLED(CONFIG_CXL_PMEM))
> +	if (IS_ENABLED(CONFIG_CXL_PMEM)) {
>  		rc = device_for_each_child(&root_port->dev, root_port,
>  					   add_root_nvdimm_bridge);
> -	if (rc < 0)
> -		return rc;
> +		if (rc < 0)
> +			return rc;
> +	}

No need to move this inside the "if (IS_ENABLED(CONFIG_CXL_PMEM))" that
I can see.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ