Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cxl/mem: Introduce a driver for CXL-2.0-Type-3 endpoints

The CXL.mem protocol allows a device to act as a provider of "System
RAM" and/or "Persistent Memory" that is fully coherent as if the memory
was attached to the typical CPU memory controller.

With the CXL-2.0 specification a PCI endpoint can implement a "Type-3"
device interface and give the operating system control over "Host
Managed Device Memory". See section 2.3 Type 3 CXL Device.

The memory range exported by the device may optionally be described by
the platform firmware memory map, or by infrastructure like LIBNVDIMM to
provision persistent memory capacity from one, or more, CXL.mem devices.

A pre-requisite for Linux-managed memory-capacity provisioning is this
cxl_mem driver that can speak the mailbox protocol defined in section
8.2.8.4 Mailbox Registers.

For now just land the initial driver boiler-plate and Documentation/
infrastructure.

Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: David Rientjes <rientjes@google.com> (v1)
Cc: Jonathan Corbet <corbet@lwn.net>
Link: https://www.computeexpresslink.org/download-the-specification
Link: https://lore.kernel.org/r/20210217040958.1354670-2-ben.widawsky@intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+149
+12
Documentation/driver-api/cxl/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ==================== 4 + Compute Express Link 5 + ==================== 6 + 7 + .. toctree:: 8 + :maxdepth: 1 9 + 10 + memory-devices 11 + 12 + .. only:: subproject and html
+15
Documentation/driver-api/cxl/memory-devices.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: <isonum.txt> 3 + 4 + =================================== 5 + Compute Express Link Memory Devices 6 + =================================== 7 + 8 + A Compute Express Link Memory Device is a CXL component that implements the 9 + CXL.mem protocol. It contains some amount of volatile memory, persistent memory, 10 + or both. It is enumerated as a PCI device for configuration and passing 11 + messages over an MMIO mailbox. Its contribution to the System Physical 12 + Address space is handled via HDM (Host Managed Device Memory) decoders 13 + that optionally define a device's contribution to an interleaved address 14 + range across multiple devices underneath a host-bridge or interleaved 15 + across host-bridges.
+1
Documentation/driver-api/index.rst
··· 35 35 usb/index 36 36 firewire 37 37 pci/index 38 + cxl/index 38 39 spi 39 40 i2c 40 41 ipmb
+1
drivers/Kconfig
··· 6 6 source "drivers/amba/Kconfig" 7 7 source "drivers/eisa/Kconfig" 8 8 source "drivers/pci/Kconfig" 9 + source "drivers/cxl/Kconfig" 9 10 source "drivers/pcmcia/Kconfig" 10 11 source "drivers/rapidio/Kconfig" 11 12
+1
drivers/Makefile
··· 73 73 obj-y += base/ block/ misc/ mfd/ nfc/ 74 74 obj-$(CONFIG_LIBNVDIMM) += nvdimm/ 75 75 obj-$(CONFIG_DAX) += dax/ 76 + obj-$(CONFIG_CXL_BUS) += cxl/ 76 77 obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/ 77 78 obj-$(CONFIG_NUBUS) += nubus/ 78 79 obj-y += macintosh/
+35
drivers/cxl/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + menuconfig CXL_BUS 3 + tristate "CXL (Compute Express Link) Devices Support" 4 + depends on PCI 5 + help 6 + CXL is a bus that is electrically compatible with PCI Express, but 7 + layers three protocols on that signalling (CXL.io, CXL.cache, and 8 + CXL.mem). The CXL.cache protocol allows devices to hold cachelines 9 + locally, the CXL.mem protocol allows devices to be fully coherent 10 + memory targets, the CXL.io protocol is equivalent to PCI Express. 11 + Say 'y' to enable support for the configuration and management of 12 + devices supporting these protocols. 13 + 14 + if CXL_BUS 15 + 16 + config CXL_MEM 17 + tristate "CXL.mem: Memory Devices" 18 + help 19 + The CXL.mem protocol allows a device to act as a provider of 20 + "System RAM" and/or "Persistent Memory" that is fully coherent 21 + as if the memory was attached to the typical CPU memory 22 + controller. 23 + 24 + Say 'y/m' to enable a driver (named "cxl_mem.ko" when built as 25 + a module) that will attach to CXL.mem devices for 26 + configuration, provisioning, and health monitoring. This 27 + driver is required for dynamic provisioning of CXL.mem 28 + attached memory which is a prerequisite for persistent memory 29 + support. Typically volatile memory is mapped by platform 30 + firmware and included in the platform memory map, but in some 31 + cases the OS is responsible for mapping that memory. See 32 + Chapter 2.3 Type 3 CXL Device in the CXL 2.0 specification. 33 + 34 + If unsure say 'm'. 35 + endif
+4
drivers/cxl/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_CXL_MEM) += cxl_mem.o 3 + 4 + cxl_mem-y := mem.o
+62
drivers/cxl/mem.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ 3 + #include <linux/module.h> 4 + #include <linux/pci.h> 5 + #include <linux/io.h> 6 + #include "pci.h" 7 + 8 + static int cxl_mem_dvsec(struct pci_dev *pdev, int dvsec) 9 + { 10 + int pos; 11 + 12 + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DVSEC); 13 + if (!pos) 14 + return 0; 15 + 16 + while (pos) { 17 + u16 vendor, id; 18 + 19 + pci_read_config_word(pdev, pos + PCI_DVSEC_HEADER1, &vendor); 20 + pci_read_config_word(pdev, pos + PCI_DVSEC_HEADER2, &id); 21 + if (vendor == PCI_DVSEC_VENDOR_ID_CXL && dvsec == id) 22 + return pos; 23 + 24 + pos = pci_find_next_ext_capability(pdev, pos, 25 + PCI_EXT_CAP_ID_DVSEC); 26 + } 27 + 28 + return 0; 29 + } 30 + 31 + static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id) 32 + { 33 + struct device *dev = &pdev->dev; 34 + int regloc; 35 + 36 + regloc = cxl_mem_dvsec(pdev, PCI_DVSEC_ID_CXL_REGLOC_OFFSET); 37 + if (!regloc) { 38 + dev_err(dev, "register location dvsec not found\n"); 39 + return -ENXIO; 40 + } 41 + 42 + return 0; 43 + } 44 + 45 + static const struct pci_device_id cxl_mem_pci_tbl[] = { 46 + /* PCI class code for CXL.mem Type-3 Devices */ 47 + { PCI_DEVICE_CLASS((PCI_CLASS_MEMORY_CXL << 8 | CXL_MEMORY_PROGIF), ~0)}, 48 + { /* terminate list */ }, 49 + }; 50 + MODULE_DEVICE_TABLE(pci, cxl_mem_pci_tbl); 51 + 52 + static struct pci_driver cxl_mem_driver = { 53 + .name = KBUILD_MODNAME, 54 + .id_table = cxl_mem_pci_tbl, 55 + .probe = cxl_mem_probe, 56 + .driver = { 57 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 58 + }, 59 + }; 60 + 61 + MODULE_LICENSE("GPL v2"); 62 + module_pci_driver(cxl_mem_driver);
+17
drivers/cxl/pci.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ 3 + #ifndef __CXL_PCI_H__ 4 + #define __CXL_PCI_H__ 5 + 6 + #define CXL_MEMORY_PROGIF 0x10 7 + 8 + /* 9 + * See section 8.1 Configuration Space Registers in the CXL 2.0 10 + * Specification 11 + */ 12 + #define PCI_DVSEC_VENDOR_ID_CXL 0x1E98 13 + #define PCI_DVSEC_ID_CXL 0x0 14 + 15 + #define PCI_DVSEC_ID_CXL_REGLOC_OFFSET 0x8 16 + 17 + #endif /* __CXL_PCI_H__ */
+1
include/linux/pci_ids.h
··· 51 51 #define PCI_BASE_CLASS_MEMORY 0x05 52 52 #define PCI_CLASS_MEMORY_RAM 0x0500 53 53 #define PCI_CLASS_MEMORY_FLASH 0x0501 54 + #define PCI_CLASS_MEMORY_CXL 0x0502 54 55 #define PCI_CLASS_MEMORY_OTHER 0x0580 55 56 56 57 #define PCI_BASE_CLASS_BRIDGE 0x06