cxl/pmem: Format the nvdimm serial number as unsigned decimal

The CXL NVDIMM security passphrase key description and the nvdimm 'id'
sysfs attribute are both derived from the CXL device serial number,
but the serial number is not formatted consistently.

The key description is formatted in hexadecimal while the 'id'
attribute is formatted in decimal. As a result, ndctl stores the key
using a decimal description while the kernel later looks it up using
a hexadecimal description. For serial numbers of 10 and above, the
descriptions no longer match, preventing automatic unlock after
reboot.

The decimal formatting has a second problem: both the key description
and the 'id' attribute use the signed %lld format for a u64 PCIe
Device Serial Number. Devices whose vendor OUI sets bit 63, such as
Montage CXL devices, appear with negative decimal serial numbers.

Format the security key description and 'id' attribute as unsigned
decimal, %llu, and document that the 'id' attribute is an unsigned
decimal value.

The key lookup mismatch was exposed by CXL unit test cxl-security.sh
when cxl_test mock serial numbers were extended to 10 and above.

A work around is described for ndctl load-key users here:
https://github.com/pmem/ndctl/issues/299

Cc: stable@vger.kernel.org
Fixes: b5807c80b5 ("cxl: add dimm_id support for __nvdimm_create()")
Acked-by: Dan Williams <djbw@kernel.org>
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Link: https://patch.msgid.link/2c673a5ba0a8fa93ad160578e193bd556091fa95.1784924949.git.alison.schofield@intel.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
This commit is contained in:
Alison Schofield 2026-07-24 13:37:17 -07:00 committed by Dave Jiang
parent 4ee7514066
commit 8a80d3d65c
4 changed files with 11 additions and 7 deletions

View File

@ -48,7 +48,8 @@ What: /sys/bus/nd/devices/nmemX/cxl/id
Date: November 2022
KernelVersion: 6.2
Contact: Dave Jiang <dave.jiang@intel.com>
Description: (RO) Show the id (serial) of the device. This is CXL specific.
Description: (RO) Show the id (serial) of the device, formatted as an
unsigned 64-bit decimal value. This is CXL specific.
What: /sys/bus/nd/devices/nmemX/cxl/provider
Date: November 2022

View File

@ -219,12 +219,14 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_nvdimm_bridge *cxl_nvb,
dev->bus = &cxl_bus_type;
dev->type = &cxl_nvdimm_type;
/*
* A "%llx" string is 17-bytes vs dimm_id that is max
* NVDIMM_KEY_DESC_LEN
* dev_id is the nvdimm dimm_id used for security key lookup.
* It must match id_show(), which emits the CXL serial as an
* unsigned decimal. A u64 decimal string is at most 20 digits
* plus NUL.
*/
BUILD_BUG_ON(sizeof(cxl_nvd->dev_id) < 17 ||
BUILD_BUG_ON(sizeof(cxl_nvd->dev_id) < 21 ||
sizeof(cxl_nvd->dev_id) > NVDIMM_KEY_DESC_LEN);
sprintf(cxl_nvd->dev_id, "%llx", cxlmd->cxlds->serial);
sprintf(cxl_nvd->dev_id, "%llu", cxlmd->cxlds->serial);
return cxl_nvd;
}

View File

@ -503,7 +503,8 @@ struct cxl_nvdimm_bridge {
struct nvdimm_bus_descriptor nd_desc;
};
#define CXL_DEV_ID_LEN 19
/* Holds a u64 serial as a decimal string: up to 20 digits + NUL */
#define CXL_DEV_ID_LEN 21
enum {
CXL_NVD_F_INVALIDATED = 0,

View File

@ -52,7 +52,7 @@ static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_dev_state *cxlds = cxl_nvd->cxlmd->cxlds;
return sysfs_emit(buf, "%lld\n", cxlds->serial);
return sysfs_emit(buf, "%llu\n", cxlds->serial);
}
static DEVICE_ATTR_RO(id);