Logo

Linux 内核

6.13.0-rc6

快速搜索

目录

  • 开发流程
  • 提交补丁
  • 行为准则
  • 维护者手册
  • 所有开发流程文档
  • 核心 API
  • 驱动程序 API
    • 驱动程序作者的通用信息
    • 有用的支持库
    • 总线级文档
      • 辅助总线
      • 计算快线链路
      • EISA 总线支持
      • 火线 (IEEE 1394) 驱动程序接口指南
      • I3C 子系统
      • ISA 驱动程序
      • MEN 变色龙总线
      • Linux PCI 驱动程序实现者 API 指南
      • Linux RapidIO 子系统
      • Linux 内核 SLIMbus 支持
      • Linux USB API
      • Virtio
      • VME 设备驱动程序
      • W1:达拉斯 1 线总线
      • 用于通用 FPGA 接口的 Xillybus 驱动程序
    • 子系统特定 API
  • 子系统
  • 锁定
  • 许可规则
  • 编写文档
  • 开发工具
  • 测试指南
  • 黑客指南
  • 跟踪
  • 故障注入
  • 实时修补
  • Rust
  • 管理
  • 构建系统
  • 报告问题
  • 用户空间工具
  • 用户空间 API
  • 固件
  • 固件和设备树
  • CPU 架构
  • 未分类文档
  • 翻译

本页

  • 显示源代码

计算快线链路内存设备¶

计算快线链路内存设备是实现 CXL.mem 协议的 CXL 组件。它包含一定数量的易失性内存、持久性内存或两者兼而有之。它被枚举为 PCI 设备,用于配置和通过 MMIO 邮箱传递消息。它对系统物理地址空间的贡献通过 HDM(主机管理设备内存)解码器处理,这些解码器可以选择性地定义设备对主机桥下多个设备之间的交错地址范围的贡献,或跨多个主机桥的交错地址范围的贡献。

CXL 总线:操作理论¶

类似于 RAID 驱动程序如何获取磁盘对象并将它们组装成新的逻辑设备,CXL 子系统的任务是获取 PCIe 和 ACPI 对象并将它们组装成 CXL.mem 解码拓扑。CXL.mem 拓扑的运行时配置需求也类似于 RAID,因为具有相同硬件配置的不同环境可能会决定以不同的方式组装拓扑。一种方式可能会选择性能(RAID0),跨多个主机桥和端点条带化内存,而另一种方式可能会选择容错并禁用 CXL.mem 拓扑中的任何条带化。

平台固件在“CXL 根端口”(Linux 中 CXL 解码拓扑顶部的术语)枚举交错选项菜单。从那里,PCIe 拓扑决定哪些端点可以参与哪些主机桥解码方案。根端口和端点之间的路径中的每个 PCIe 交换机都会引入一个可以拆分交错的点。例如,平台固件可能会说在给定的范围内,解码仅针对 1 个主机桥,但该主机桥又可能会跨多个根端口交错循环。端口和端点之间的中间交换机可能会跨多个下游交换机端口交错循环等等。

以下是由“cxl_test”定义的 CXL 拓扑示例列表。“cxl_test”模块生成一个模拟的 CXL 拓扑,包含 2 个主机桥,每个主机桥有 2 个根端口。这些根端口中的每一个都连接到 2 路交换机,端点连接到那些下游端口,总共有 8 个端点

# cxl list -BEMPu -b cxl_test
{
  "bus":"root3",
  "provider":"cxl_test",
  "ports:root3":[
    {
      "port":"port5",
      "host":"cxl_host_bridge.1",
      "ports:port5":[
        {
          "port":"port8",
          "host":"cxl_switch_uport.1",
          "endpoints:port8":[
            {
              "endpoint":"endpoint9",
              "host":"mem2",
              "memdev":{
                "memdev":"mem2",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x1",
                "numa_node":1,
                "host":"cxl_mem.1"
              }
            },
            {
              "endpoint":"endpoint15",
              "host":"mem6",
              "memdev":{
                "memdev":"mem6",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x5",
                "numa_node":1,
                "host":"cxl_mem.5"
              }
            }
          ]
        },
        {
          "port":"port12",
          "host":"cxl_switch_uport.3",
          "endpoints:port12":[
            {
              "endpoint":"endpoint17",
              "host":"mem8",
              "memdev":{
                "memdev":"mem8",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x7",
                "numa_node":1,
                "host":"cxl_mem.7"
              }
            },
            {
              "endpoint":"endpoint13",
              "host":"mem4",
              "memdev":{
                "memdev":"mem4",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x3",
                "numa_node":1,
                "host":"cxl_mem.3"
              }
            }
          ]
        }
      ]
    },
    {
      "port":"port4",
      "host":"cxl_host_bridge.0",
      "ports:port4":[
        {
          "port":"port6",
          "host":"cxl_switch_uport.0",
          "endpoints:port6":[
            {
              "endpoint":"endpoint7",
              "host":"mem1",
              "memdev":{
                "memdev":"mem1",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0",
                "numa_node":0,
                "host":"cxl_mem.0"
              }
            },
            {
              "endpoint":"endpoint14",
              "host":"mem5",
              "memdev":{
                "memdev":"mem5",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x4",
                "numa_node":0,
                "host":"cxl_mem.4"
              }
            }
          ]
        },
        {
          "port":"port10",
          "host":"cxl_switch_uport.2",
          "endpoints:port10":[
            {
              "endpoint":"endpoint16",
              "host":"mem7",
              "memdev":{
                "memdev":"mem7",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x6",
                "numa_node":0,
                "host":"cxl_mem.6"
              }
            },
            {
              "endpoint":"endpoint11",
              "host":"mem3",
              "memdev":{
                "memdev":"mem3",
                "pmem_size":"256.00 MiB (268.44 MB)",
                "ram_size":"256.00 MiB (268.44 MB)",
                "serial":"0x2",
                "numa_node":0,
                "host":"cxl_mem.2"
              }
            }
          ]
        }
      ]
    }
  ]
}

在该列表中,每个“根”、“端口”和“端点”对象都对应一个内核 ‘struct cxl_port’ 对象。‘cxl_port’ 是一个可以将 CXL.mem 解码到其后代的设备。因此,“根”声明非 PCIe 可枚举平台解码范围,并将它们解码为“端口”,“端口”解码为“端点”,“端点”表示从 SPA(系统物理地址)到 DPA(设备物理地址)的解码。

继续 RAID 类比,磁盘既有拓扑元数据,也有设备上的元数据,这些元数据决定了 RAID 集的组装。CXL 端口拓扑和 CXL 端口链接状态是 CXL.mem 集组装的元数据。CXL 端口拓扑是通过 CXL.mem 设备的到达来枚举的。也就是说,除非并且直到 PCIe 核心将 cxl_pci 驱动程序附加到 CXL 内存扩展器,否则 CXL 端口对象没有任何作用。相反,对于热插拔/移除场景,Linux PCI 核心不需要拆除交换机级别的 CXL 资源,因为端点 ->remove() 事件会清理为支持该内存扩展器而建立的端口数据。

端口元数据和给定内存设备可能参与的潜在解码方案可以通过如下命令确定

# cxl list -BDMu -d root -m mem3
{
  "bus":"root3",
  "provider":"cxl_test",
  "decoders:root3":[
    {
      "decoder":"decoder3.1",
      "resource":"0x8030000000",
      "size":"512.00 MiB (536.87 MB)",
      "volatile_capable":true,
      "nr_targets":2
    },
    {
      "decoder":"decoder3.3",
      "resource":"0x8060000000",
      "size":"512.00 MiB (536.87 MB)",
      "pmem_capable":true,
      "nr_targets":2
    },
    {
      "decoder":"decoder3.0",
      "resource":"0x8020000000",
      "size":"256.00 MiB (268.44 MB)",
      "volatile_capable":true,
      "nr_targets":1
    },
    {
      "decoder":"decoder3.2",
      "resource":"0x8050000000",
      "size":"256.00 MiB (268.44 MB)",
      "pmem_capable":true,
      "nr_targets":1
    }
  ],
  "memdevs:root3":[
    {
      "memdev":"mem3",
      "pmem_size":"256.00 MiB (268.44 MB)",
      "ram_size":"256.00 MiB (268.44 MB)",
      "serial":"0x2",
      "numa_node":0,
      "host":"cxl_mem.2"
    }
  ]
}

...它查询 CXL 拓扑,询问“给定内核设备名称为 ‘mem3’ 的 CXL 内存扩展器,该设备可以参与哪些平台级别的解码范围”。给定的扩展器可以同时参与多个 CXL.mem 交错集,具体取决于它有多少解码器资源。在此示例中,mem3 可以参与跨越主机桥的一个或多个 PMEM 交错、针对单个主机桥的 PMEM 交错、跨越 2 个主机桥的易失性内存交错以及仅针对单个主机桥的易失性内存交错。

相反,可以参与给定平台级别解码方案的内存设备可以通过如下命令确定

# cxl list -MDu -d 3.2
[
  {
    "memdevs":[
      {
        "memdev":"mem1",
        "pmem_size":"256.00 MiB (268.44 MB)",
        "ram_size":"256.00 MiB (268.44 MB)",
        "serial":"0",
        "numa_node":0,
        "host":"cxl_mem.0"
      },
      {
        "memdev":"mem5",
        "pmem_size":"256.00 MiB (268.44 MB)",
        "ram_size":"256.00 MiB (268.44 MB)",
        "serial":"0x4",
        "numa_node":0,
        "host":"cxl_mem.4"
      },
      {
        "memdev":"mem7",
        "pmem_size":"256.00 MiB (268.44 MB)",
        "ram_size":"256.00 MiB (268.44 MB)",
        "serial":"0x6",
        "numa_node":0,
        "host":"cxl_mem.6"
      },
      {
        "memdev":"mem3",
        "pmem_size":"256.00 MiB (268.44 MB)",
        "ram_size":"256.00 MiB (268.44 MB)",
        "serial":"0x2",
        "numa_node":0,
        "host":"cxl_mem.2"
      }
    ]
  },
  {
    "root decoders":[
      {
        "decoder":"decoder3.2",
        "resource":"0x8050000000",
        "size":"256.00 MiB (268.44 MB)",
        "pmem_capable":true,
        "nr_targets":1
      }
    ]
  }
]

...其中解码器的命名方案为 “decoder.”。

驱动程序基础结构¶

本节介绍 CXL 内存设备的驱动程序基础结构。

CXL 内存设备¶

这实现了计算快线链路规范定义的 CXL 设备的 PCI 独有功能。CXL 设备可能会在未启用 CXL 的情况下显示某些功能。虽然此驱动程序侧重于 CXL 设备的 PCI 特定方面,但它绑定到特定的 CXL 内存设备类代码,因此 cxl_pci 的实现侧重于 CXL 内存设备。

该驱动程序有几个职责,主要包括
  • 创建 memX 设备并在 CXL 总线上注册。

  • 枚举设备的寄存器接口并映射它们。

  • 使用 cxl_core 注册 nvdimm 桥接设备。

  • 使用 cxl_core 注册 CXL 邮箱。

int __cxl_pci_mbox_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *mbox_cmd)¶

执行邮箱命令

参数

struct cxl_mailbox *cxl_mbox

CXL 邮箱上下文

struct cxl_mbox_cmd *mbox_cmd

要发送到内存设备的命令。

上下文

任何上下文。期望持有 mbox_mutex。

返回

如果在等待完成时发生超时,则返回 -ETIMEDOUT。成功时返回 0。

调用者应检查 mbox_cmd 中的返回值,以确保它成功。

描述

这是 CXL 邮箱发送命令的通用形式,因此仅使用邮箱功能 ID 定义的寄存器 - CXL 2.0 8.2.8.4。内存设备以及其他类型的 CXL 设备在发生错误时可能会提供更多信息。希望发送邮箱命令的驱动程序工具应使用包装器命令。

CXL 规范允许最多两个邮箱。其目的是让主邮箱由操作系统控制,而辅助邮箱由系统固件使用。这允许操作系统和固件与设备通信,而无需彼此协调。该驱动程序仅使用主邮箱。

CXL 内存端点设备和交换机是参与 CXL.mem 协议的 CXL 功能设备。它们的功能建立在 CXL.io 协议之上,该协议允许通过标准 PCI 机制枚举和配置组件。

cxl_mem 驱动程序拥有启动此 CXL.mem 功能的枚举权。通过检测到具有 CXL 功能的端点,驱动程序将向上查找它连接的平台特定端口,并确定路径中是否存在中间交换机。如果有交换机,则次要操作是枚举这些交换机(在 cxl_core 中实现)。最后,cxl_mem 驱动程序将它绑定的设备添加为 CXL 端点端口,以便在更高级别的操作中使用。

struct cxl_memdev¶

表示 Type-3 内存设备的 CXL 总线对象

定义:

struct cxl_memdev {
    struct device dev;
    struct cdev cdev;
    struct cxl_dev_state *cxlds;
    struct work_struct detach_work;
    struct cxl_nvdimm_bridge *cxl_nvb;
    struct cxl_nvdimm *cxl_nvd;
    struct cxl_port *endpoint;
    int id;
    int depth;
};

成员

dev

驱动程序核心设备对象

cdev

用于 ioctl 操作的字符设备核心对象

cxlds

支持此设备的设备状态

detach_work

活动 memdev 在其祖先中丢失了一个端口

cxl_nvb

如果存在,协调 cxl_nvd 的删除

cxl_nvd

如果设备支持 pmem,则可选桥接到 nvdimm

endpoint

此内存设备与 CXL 端口拓扑的连接

id

此 memdev 实例的 ID 号。

depth

端点端口深度

struct cxl_mbox_cmd¶

要提交给硬件的命令。

定义:

struct cxl_mbox_cmd {
    u16 opcode;
    void *payload_in;
    void *payload_out;
    size_t size_in;
    size_t size_out;
    size_t min_out;
    int poll_count;
    int poll_interval_ms;
    u16 return_code;
};

成员

opcode

(输入)提交给硬件的命令集和命令。

payload_in

(输入)指向输入有效负载的指针。

payload_out

(输出)指向输出有效负载的指针。必须由调用者分配。

size_in

(输入)要从 payload_in 加载的字节数。

size_out

(输入)加载到 payload_out 中的最大字节数。(输出)设备生成的字节数。对于固定大小的输出命令,始终期望它是确定的。对于可变大小的输出命令,它会告诉写入的确切字节数。

min_out

(输入)内部命令输出有效负载大小验证

poll_count

(输入)要尝试的超时次数。

poll_interval_ms

(输入)邮箱后台命令轮询间隔超时之间的时间。

return_code

(输出)从硬件返回的错误代码。

描述

这是将命令发送到硬件的主要机制。除了 payload_* 之外的所有字段都与 CXL 2.0 8.2.8.4.5 命令寄存器部分中描述的字段完全对应。payload_in 和 payload_out 被写入,并从 CXL 2.0 8.2.8.4.8 中定义的命令有效负载寄存器读取。

struct cxl_event_state¶

事件日志驱动程序状态

定义:

struct cxl_event_state {
    struct cxl_get_event_payload *buf;
    struct mutex log_lock;
};

成员

buf

用于接收事件数据的缓冲区

log_lock

序列化 event_buf 和日志使用

struct cxl_poison_state¶

驱动程序毒化状态信息

定义:

struct cxl_poison_state {
    u32 max_errors;
    unsigned long enabled_cmds[BITS_TO_LONGS(CXL_POISON_ENABLED_MAX)];
    struct cxl_mbox_poison_out *list_out;
    struct mutex lock;
};

成员

max_errors

设备缓存中保存的最大介质错误记录数

enabled_cmds

CEL 中启用的所有毒化命令

list_out

设备返回的毒化列表有效载荷

lock

保护对毒化列表的读取

描述

对毒化列表的读取是同步的,以确保读取器不会获得不完整的列表,因为他们的请求与同一 DPA 范围的另一个读取请求重叠(被中断或先于)。CXL 规范 3.0 第 8.2.9.8.4.1 节

struct cxl_fw_state¶

固件上传/激活状态

定义:

struct cxl_fw_state {
    unsigned long state[BITS_TO_LONGS(CXL_FW_STATE_BITS)];
    bool oneshot;
    int num_slots;
    int cur_slot;
    int next_slot;
};

成员

state

fw_uploader 状态位掩码

oneshot

固件上传是否适合单次传输

num_slots

可用的固件槽数量

cur_slot

当前激活的槽号

next_slot

新固件的槽号

struct cxl_security_state¶

设备安全状态

定义:

struct cxl_security_state {
    unsigned long state;
    unsigned long enabled_cmds[BITS_TO_LONGS(CXL_SEC_ENABLED_MAX)];
    int poll_tmo_secs;
    bool sanitize_active;
    struct delayed_work poll_dwork;
    struct kernfs_node *sanitize_node;
};

成员

state

上次安全操作的状态

enabled_cmds

CEL 中启用的所有安全命令

poll_tmo_secs

轮询超时

sanitize_active

清除完成挂起

poll_dwork

轮询工作项

sanitize_node

用于通知的清除 sysfs 文件

struct cxl_dpa_perf¶

DPA 性能属性条目

定义:

struct cxl_dpa_perf {
    struct range dpa_range;
    struct access_coordinate coord[ACCESS_COORDINATE_MAX];
    struct access_coordinate cdat_coord[ACCESS_COORDINATE_MAX];
    int qos_class;
};

成员

dpa_range

DPA 地址范围

coord

QoS 性能数据(即延迟、带宽)

cdat_coord

来自 CDAT 的原始 QoS 性能数据

qos_class

QoS 类 Cookie

struct cxl_dev_state¶

驱动程序设备状态

定义:

struct cxl_dev_state {
    struct device *dev;
    struct cxl_memdev *cxlmd;
    struct cxl_register_map reg_map;
    struct cxl_regs regs;
    int cxl_dvsec;
    bool rcd;
    bool media_ready;
    struct resource dpa_res;
    struct resource pmem_res;
    struct resource ram_res;
    u64 serial;
    enum cxl_devtype type;
    struct cxl_mailbox cxl_mbox;
};

成员

dev

与此 CXL 状态关联的设备

cxlmd

表示 dev 的 CXL.mem 功能的设备

reg_map

组件和 ras 寄存器映射参数

regs

已解析的寄存器块

cxl_dvsec

到 PCIe 设备 DVSEC 的偏移量

rcd

在 RCD 模式下运行(CXL 3.0 9.11.8 连接到 RCH 的 CXL 设备)

media_ready

指示设备介质是否可用

dpa_res

设备的整体 DPA 资源树

pmem_res

活动的持久内存容量配置

ram_res

活动的易失性内存容量配置

serial

PCIe 设备序列号

type

通用内存类设备或特定供应商的内存设备

cxl_mbox

CXL 邮箱上下文

描述

cxl_dev_state 表示 CXL 驱动程序/设备状态。它提供了一个到邮箱命令的接口,以及一些关于设备的缓存数据。目前只表示内存设备。

struct cxl_memdev_state¶

通用 Type-3 内存设备类驱动程序数据

定义:

struct cxl_memdev_state {
    struct cxl_dev_state cxlds;
    size_t lsa_size;
    char firmware_version[0x10];
    unsigned long enabled_cmds[BITS_TO_LONGS(CXL_MEM_COMMAND_ID_MAX)];
    unsigned long exclusive_cmds[BITS_TO_LONGS(CXL_MEM_COMMAND_ID_MAX)];
    u64 total_bytes;
    u64 volatile_only_bytes;
    u64 persistent_only_bytes;
    u64 partition_align_bytes;
    u64 active_volatile_bytes;
    u64 active_persistent_bytes;
    u64 next_volatile_bytes;
    u64 next_persistent_bytes;
    struct cxl_dpa_perf ram_perf;
    struct cxl_dpa_perf pmem_perf;
    struct cxl_event_state event;
    struct cxl_poison_state poison;
    struct cxl_security_state security;
    struct cxl_fw_state fw;
};

成员

cxlds

Type-2 和 Type-3 设备通用的核心驱动程序状态

lsa_size

标签存储区域的大小(CXL 2.0 8.2.9.5.1.1 识别内存设备)

firmware_version

内存设备的固件版本。

enabled_cmds

在 CEL 中发现的启用的硬件命令。

exclusive_cmds

仅内核内部的命令

total_bytes

所有可能容量的总和

volatile_only_bytes

硬易失性容量

persistent_only_bytes

硬持久容量

partition_align_bytes

可分区容量的对齐大小

active_volatile_bytes

硬 + 软易失性的总和

active_persistent_bytes

硬 + 软持久性的总和

next_volatile_bytes

易失性容量更改等待设备重置

next_persistent_bytes

持久容量更改等待设备重置

ram_perf

与 RAM 分区匹配的性能数据条目

pmem_perf

与 PMEM 分区匹配的性能数据条目

event

事件日志驱动程序状态

poison

毒化驱动程序状态信息

security

安全驱动程序状态信息

fw

固件上传/激活状态

描述

CXL 8.1.12.1 PCI 标头 - 类代码寄存器内存设备定义了常见的内存设备功能,例如邮箱的存在以及与之相关的功能,例如识别内存设备和获取分区信息。有关容量参数的详细信息,请参见 CXL 3.0 8.2.9.8.2 容量配置和标签存储。

struct cxl_mem_command¶

内存设备命令的驱动程序表示

定义:

struct cxl_mem_command {
    struct cxl_command_info info;
    enum cxl_opcode opcode;
    u32 flags;
#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0);
};

成员

info

命令信息,因为它对于 UAPI 存在

opcode

邮箱协议使用的实际位

flags

影响驱动程序行为的标志集。

  • CXL_CMD_FLAG_FORCE_ENABLE:在发生错误的情况下,无论硬件可能通告了什么,驱动程序都将启用带有此标志的命令。

描述

cxl_mem_command 是驱动程序内部表示的驱动程序支持的命令。其中一些命令可能不受硬件支持。驱动程序将使用 info 来验证用户传入的字段,然后将 opcode 提交给硬件。

请参见 struct cxl_command_info。

struct cxl_hdm¶

HDM 解码器寄存器和缓存/解码的功能

定义:

struct cxl_hdm {
    struct cxl_component_regs regs;
    unsigned int decoder_count;
    unsigned int target_count;
    unsigned int interleave_mask;
    unsigned long iw_cap_mask;
    struct cxl_port *port;
};

成员

regs

映射的寄存器,请参见 devm_cxl_setup_hdm()

decoder_count

此端口的解码器数量

target_count

对于交换机解码器,最大下游端口目标

interleave_mask

交错粒度功能,请参见 check_interleave_cap()

iw_cap_mask

支持的交错方式的位掩码,请参见 check_interleave_cap()

port

映射的 cxl_port,请参见 devm_cxl_setup_hdm()

void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds)¶

原子地禁用用户 cxl 命令

参数

struct cxl_memdev_state *mds

要操作的设备状态

unsigned long *cmds

标记为互斥的命令的位图

描述

以写入模式获取 cxl_memdev_rwsem,以刷新正在进行的 ioctl 路径调用,然后禁用使用 cmds 中设置的命令 ID 的命令的未来执行。

void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds)¶

原子地启用用户 cxl 命令

参数

struct cxl_memdev_state *mds

要修改的设备状态

unsigned long *cmds

标记为对用户空间可用的命令的位图

int cxl_mem_get_fw_info(struct cxl_memdev_state *mds)¶

获取固件信息

参数

struct cxl_memdev_state *mds

操作的设备数据

描述

检索指定设备的固件信息。

请参见 CXL-3.0 8.2.9.3.1 获取固件信息

返回

如果没有错误则为 0:或者邮箱命令的结果。

int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot)¶

激活固件

参数

struct cxl_memdev_state *mds

操作的设备数据

int slot

要激活的槽号

描述

激活指定设备的给定槽中的固件。

请参见 CXL-3.0 8.2.9.3.3 激活固件

返回

如果没有错误则为 0:或者邮箱命令的结果。

int cxl_mem_abort_fw_xfer(struct cxl_memdev_state *mds)¶

中止正在进行的固件传输

参数

struct cxl_memdev_state *mds

操作的设备数据

描述

中止指定设备的正在进行的固件传输。

参见 CXL-3.0 8.2.9.3.2 传输固件

返回

如果没有错误则为 0:或者邮箱命令的结果。

CXL 端口¶

端口驱动程序通过 PCI 枚举 dport,并通过代理注册端口时传递的 component_reg_phys 值扫描 HDM (主机管理设备内存) 解码器资源。CXL 根端口(由平台固件描述)的所有子端口都在此驱动程序上下文中进行管理。每个驱动程序实例负责拆除其直接子端口的驱动程序上下文。此操作的锁定由 CONFIG_PROVE_CXL_LOCKING 验证。

此驱动程序提供的主要服务是向其他驱动程序提供 API 以利用解码器,并向用户空间(通过绑定状态)指示整个 PCIe 拓扑中 CXL.mem 协议的连接性。

CXL 核心¶

CXL 核心对象(如端口、解码器和区域)在子系统驱动程序 cxl_acpi、cxl_pci 和核心驱动程序(端口驱动程序、区域驱动程序、nvdimm 对象驱动程序等)之间共享。

struct cxl_register_map¶

DVSEC 收集的寄存器块映射参数

定义:

struct cxl_register_map {
    struct device *host;
    void __iomem *base;
    resource_size_t resource;
    resource_size_t max_size;
    u8 reg_type;
    union {
        struct cxl_component_reg_map component_map;
        struct cxl_device_reg_map device_map;
        struct cxl_pmu_reg_map pmu_map;
    };
};

成员

host

用于 devm 操作和日志记录的设备

base

寄存器块 BAR + block_offset 的虚拟基址

resource

寄存器块的物理资源基址

max_size

执行寄存器搜索的最大映射大小

reg_type

参见枚举 cxl_regloc_type

{unnamed_union}

匿名

component_map

组件寄存器的 cxl_reg_map

device_map

设备寄存器的 cxl_reg_map

pmu_map

CXL 性能监视单元的 cxl_reg_map

struct cxl_decoder¶

公共 CXL HDM 解码器属性

定义:

struct cxl_decoder {
    struct device dev;
    int id;
    struct range hpa_range;
    int interleave_ways;
    int interleave_granularity;
    enum cxl_decoder_type target_type;
    struct cxl_region *region;
    unsigned long flags;
    int (*commit)(struct cxl_decoder *cxld);
    void (*reset)(struct cxl_decoder *cxld);
};

成员

dev

此解码器的设备

id

内核设备名称 ID

hpa_range

此解码器映射的主机物理地址范围

interleave_ways

此解码中的 cxl_dport 数量

interleave_granularity

每个 dport 的数据跨度

target_type

加速器与扩展器(type2 与 type3)选择器

region

此解码器当前分配的区域

flags

内存类型功能和锁定

commit

将设置提交到硬件的设备/解码器类型特定回调

reset

重置硬件设置的设备/解码器类型特定回调

struct cxl_endpoint_decoder¶

端点 / SPA 到 DPA 解码器

定义:

struct cxl_endpoint_decoder {
    struct cxl_decoder cxld;
    struct resource *dpa_res;
    resource_size_t skip;
    enum cxl_decoder_mode mode;
    enum cxl_decoder_state state;
    int pos;
};

成员

cxld

基本 cxl_decoder_object

dpa_res

此解码器主动声明的 DPA 跨度

skip

dpa_res 中的偏移量,其中映射 cxld.hpa_range

mode

此解码器面向的内存类型 / 访问模式分区

state

自动发现状态

pos

在 cxld.region 中的交错位置

struct cxl_switch_decoder¶

交换机特定的 CXL HDM 解码器

定义:

struct cxl_switch_decoder {
    struct cxl_decoder cxld;
    int nr_targets;
    struct cxl_dport *target[];
};

成员

cxld

基本 cxl_decoder 对象

nr_targets

target 中的元素数量

target

当前解码器配置中的活动排序目标列表

描述

“交换机”解码器类型表示 cxl_port 的解码器实例,这些实例从 CXL 内存解码拓扑的根路由到端点。它们有两种类型:根级解码器(由平台固件静态定义)和中间级解码器(其中交错粒度、交错宽度和目标列表是可变的)。

struct cxl_root_decoder¶

静态平台 CXL 地址解码器

定义:

struct cxl_root_decoder {
    struct resource *res;
    atomic_t region_id;
    cxl_hpa_to_spa_fn hpa_to_spa;
    void *platform_data;
    struct mutex range_lock;
    int qos_class;
    struct cxl_switch_decoder cxlsd;
};

成员

res

用于区域分配的主机 / 父资源

region_id

用于下一个区域配置事件的区域 ID

hpa_to_spa

将 CXL 主机物理地址转换为平台系统物理地址

platform_data

平台特定的配置数据

range_lock

通过地址范围同步区域自动发现

qos_class

QoS 性能类 Cookie

cxlsd

基本 cxl 交换机解码器

struct cxl_region_params¶

区域设置

定义:

struct cxl_region_params {
    enum cxl_config_state state;
    uuid_t uuid;
    int interleave_ways;
    int interleave_granularity;
    struct resource *res;
    struct cxl_endpoint_decoder *targets[CXL_DECODER_MAX_INTERLEAVE];
    int nr_targets;
};

成员

state

允许驱动程序锁定进一步的参数更改

uuid

持久区域的唯一 ID

interleave_ways

区域中的端点数

interleave_granularity

每个端点对条带的贡献容量

res

为此区域分配的 iomem 容量

targets

当前解码器配置中的活动排序目标

nr_targets

目标数量

描述

状态转换由 cxl_region_rwsem 保护

struct cxl_region¶

CXL 区域

定义:

struct cxl_region {
    struct device dev;
    int id;
    enum cxl_decoder_mode mode;
    enum cxl_decoder_type type;
    struct cxl_nvdimm_bridge *cxl_nvb;
    struct cxl_pmem_region *cxlr_pmem;
    unsigned long flags;
    struct cxl_region_params params;
    struct access_coordinate coord[ACCESS_COORDINATE_MAX];
    struct notifier_block memory_notifier;
    struct notifier_block adist_notifier;
};

成员

dev

此区域的设备

id

此区域的 ID。ID 在所有区域中全局唯一

mode

端点解码器分配 / 访问模式

type

端点解码器目标类型

cxl_nvb

用于协调 cxlr_pmem 设置 / 关闭的 nvdimm 桥

cxlr_pmem

(对于 pmem 区域)nvdimm 桥的缓存副本

flags

区域状态标志

params

区域的活动 + 配置参数

coord

区域的 QoS 访问坐标

memory_notifier

用于将访问坐标设置为节点的通知程序

adist_notifier

用于计算节点抽象距离的通知程序

struct cxl_port¶

上游端口设备和下游端口设备的逻辑集合,用于构建 CXL 内存解码层次结构。

定义:

struct cxl_port {
    struct device dev;
    struct device *uport_dev;
    struct device *host_bridge;
    int id;
    struct xarray dports;
    struct xarray endpoints;
    struct xarray regions;
    struct cxl_dport *parent_dport;
    struct ida decoder_ida;
    struct cxl_register_map reg_map;
    int nr_dports;
    int hdm_end;
    int commit_end;
    bool dead;
    unsigned int depth;
    struct cxl_cdat {
        void *table;
        size_t length;
    } cdat;
    bool cdat_available;
    long pci_latency;
};

成员

dev

此端口的设备

uport_dev

实现上游端口功能的 PCI 或平台设备

host_bridge

此端口的平台连接点的快捷方式

id

端口设备名称的 ID

dports

解码器引用的 cxl_dport 实例

endpoints

cxl_ep 实例,此端口的子端点

regions

cxl_region_ref 实例,此端口映射的区域

parent_dport

在父级中指向此端口的 dport

decoder_ida

解码器 ID 的分配器

reg_map

组件和 ras 寄存器映射参数

nr_dports

dports 中的条目数量

hdm_end

跟踪最后分配的 HDM 解码器实例,用于分配排序

commit_end

用于跟踪最高提交解码器的游标,用于提交排序

dead

已删除最后一个 ep,强制重新创建端口

depth

此端口相对于根端口的深度。深度 0 是根端口。

cdat

缓存的 CDAT 数据

cdat_available

CDAT 属性是否应在 sysfs 中可用

pci_latency

上游延迟,以皮秒为单位

struct cxl_root¶

根 cxl_port 项的逻辑集合

定义:

struct cxl_root {
    struct cxl_port port;
    const struct cxl_root_ops *ops;
};

成员

port

cxl_port 成员

ops

cxl 根操作

struct cxl_dport¶

CXL 下游端口

定义:

struct cxl_dport {
    struct device *dport_dev;
    struct cxl_register_map reg_map;
    int port_id;
    struct cxl_rcrb_info rcrb;
    bool rch;
    struct cxl_port *port;
    struct cxl_regs regs;
    struct access_coordinate coord[ACCESS_COORDINATE_MAX];
    long link_latency;
};

成员

dport_dev

表示下游链接的 PCI 桥或固件设备

reg_map

组件和 ras 寄存器映射参数

port_id

解码器目标列表中 dport 的唯一硬件标识符

rcrb

关于根复合体寄存器块布局的数据

rch

指示是否在 RCH 或 VH 模式下枚举此 dport

port

对包含此下游端口的 cxl_port 的引用

regs

已解析的 Dport 寄存器块

coord

访问坐标(带宽和延迟性能属性)

link_latency

计算的 PCIe 下游延迟

struct cxl_ep¶

跟踪端点对端口的兴趣

定义:

struct cxl_ep {
    struct device *ep;
    struct cxl_dport *dport;
    struct cxl_port *next;
};

成员

ep

托管通用 CXL 端点(扩展器或加速器)的设备

dport

port 上哪个 dport 路由到此端点

next

跨链接连接到 dport 的 cxl 交换机端口,如果连接到端点,则为 NULL

struct cxl_region_ref¶

跟踪区域对端口的兴趣

定义:

struct cxl_region_ref {
    struct cxl_port *port;
    struct cxl_decoder *decoder;
    struct cxl_region *region;
    struct xarray endpoints;
    int nr_targets_set;
    int nr_eps;
    int nr_targets;
};

成员

port

在此引用中安装拓扑中的点

decoder

在 port 中为 region 分配的解码器

region

此引用的区域

endpoints

port 下区域成员的 cxl_ep 引用

nr_targets_set

跟踪在设置期间已编程多少目标

nr_eps

port 下的端点数量

nr_targets

到达 nr_eps 所需的不同目标数量

struct cxl_endpoint_dvsec_info¶

缓存的 DVSEC 信息

定义:

struct cxl_endpoint_dvsec_info {
    bool mem_enabled;
    int ranges;
    struct cxl_port *port;
    struct range dvsec_range[2];
};

成员

mem_enabled

初始化时 DVSEC 中 mem_enabled 的缓存值

ranges

此设备使用的活动 HDM 范围数。

port

与此信息实例关联的端点端口

dvsec_range

DVSEC 中范围的缓存属性,PCIE_DEVICE

Compute Express Link 主机管理设备内存,从 CXL 2.0 规范开始,由每个 CXL 端口和每个 CXL 端点的一系列 HDM 解码器寄存器实例管理。定义用于枚举这些寄存器和功能的通用帮助程序。

struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, struct cxl_endpoint_dvsec_info *info)¶

映射 HDM 解码器组件寄存器

参数

struct cxl_port *port

要映射的 cxl_port

struct cxl_endpoint_dvsec_info *info

缓存的 DVSEC 范围寄存器信息

int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, struct cxl_endpoint_dvsec_info *info)¶

为每个 HDM 寄存器集添加解码器对象

参数

struct cxl_hdm *cxlhdm

用于填充 HDM 功能的结构

struct cxl_endpoint_dvsec_info *info

缓存的 DVSEC 范围寄存器信息

void cxl_coordinates_combine(struct access_coordinate *out, struct access_coordinate *c1, struct access_coordinate *c2)¶

合并两个输入坐标

参数

struct access_coordinate *out

c1 和 c2 合并后的输出坐标

struct access_coordinate *c1

输入坐标

struct access_coordinate *c2

输入坐标

int cxl_endpoint_gather_bandwidth(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled, struct xarray *usp_xa, bool *gp_is_root)¶

在 xarray 中收集所有端点带宽

参数

struct cxl_region *cxlr

用于带宽计算的 CXL 区域

struct cxl_endpoint_decoder *cxled

开始的端点解码器

struct xarray *usp_xa

(输出)xarray,它收集所有以具有“struct cxl_perf_ctx”数据的上游设备索引的带宽坐标。

bool *gp_is_root

(输出)祖父节点是否为 cxl 根节点的布尔值。

返回

成功返回 0,或返回 -errno

描述

收集聚合的端点带宽,并将带宽存储在以交换机的上游设备或 RP 设备索引的 xarray 中。每个端点都包含来自端点 CDAT 的 DSLBIS、端点上游链路带宽以及交换机 CDAT 的 SSLBIS 中的带宽最小值,用于交换机上游端口到与该端点关联的下游端口。如果设备直接连接到 RP,则不涉及 SSLBIS。

struct xarray *cxl_switch_gather_bandwidth(struct cxl_region *cxlr, struct xarray *input_xa, bool *gp_is_root)¶

在 xarray 中收集交换机级别的所有带宽

参数

struct cxl_region *cxlr

正在操作的区域

struct xarray *input_xa

以交换机的上游设备索引的 xarray,数据为“struct cxl_perf_ctx”

bool *gp_is_root

(输出)祖父节点是否为 cxl 根节点的布尔值。

返回

每个父交换机或根端口的 cxl_perf_ctx 结果的 xarray

或 ERR_PTR(-errno)

描述

遍历 xarray。取下游计算的带宽、上游链路带宽以及上游交换机的 SSLBIS(如果存在)的最小值。将结果带宽总和到交换机上游设备或 RP 设备下。如果存在交换机,该函数可以多次遍历交换机。

struct xarray *cxl_rp_gather_bandwidth(struct xarray *xa)¶

处理根端口级别的带宽收集

参数

struct xarray *xa

保存 cxl_perf_ctx 的 xarray,该结构具有在每个根端口设备下方计算的带宽。

返回

保存每个主机桥的 cxl_perf_ctx 的 xarray 或 ERR_PTR(-errno)

struct xarray *cxl_hb_gather_bandwidth(struct xarray *xa)¶

处理主机桥级别的带宽收集

参数

struct xarray *xa

保存 cxl_perf_ctx 的 xarray,该结构具有在每个主机桥下方计算的带宽。

返回

保存每个 ACPI0017 设备的 cxl_perf_ctx 的 xarray 或 ERR_PTR(-errno)

void cxl_region_update_bandwidth(struct cxl_region *cxlr, struct xarray *input_xa)¶

更新区域的带宽访问坐标

参数

struct cxl_region *cxlr

正在操作的区域

struct xarray *input_xa

xarray 保存每个 ACPI0017 实例的计算带宽的 cxl_perf_ctx

void cxl_region_shared_upstream_bandwidth_update(struct cxl_region *cxlr)¶

重新计算区域的带宽

参数

struct cxl_region *cxlr

要重新计算的 cxl 区域

描述

该函数自下而上遍历拓扑并计算带宽。它从端点开始,在交换机(如果有)处进行处理,在根端口级别进行处理,在主机桥级别进行处理,最后在区域进行聚合。

CXL 核心提供一组可供 CXL 感知驱动程序使用的接口。这些接口允许创建、修改和销毁区域、内存设备、端口和解码器。CXL 感知驱动程序必须通过这些接口向 CXL 核心注册,以便能够参与跨设备的交错协调。CXL 核心还建立并维护与 nvdimm 子系统的桥梁。

CXL 核心引入 sysfs 层次结构来控制核心实例化的设备。

struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport)¶

在 CXL 内存解码层次结构中注册一个 cxl_port。

参数

struct device *host

用于 devm 操作的主机设备。

struct device *uport_dev

实现此上游端口的“物理”设备。

resource_size_t component_reg_phys

(可选)用于可配置的 cxl_port 实例。

struct cxl_dport *parent_dport

CXL 内存解码层次结构中的下一跳。

struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, int port_id, resource_size_t component_reg_phys)¶

将 VH 下游端口数据附加到 cxl_port。

参数

struct cxl_port *port

引用此 dport 的 cxl_port。

struct device *dport_dev

表示 dport 的固件或 PCI 设备。

int port_id

解码器目标列表中的此 dport 的标识符。

resource_size_t component_reg_phys

CXL 组件寄存器的可选位置。

描述

请注意,dport 会附加到端口主机(对于根端口)或端口本身(对于交换机端口)的 devm 释放操作中。

struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, resource_size_t rcrb)¶

将 RCH 下游端口数据附加到 cxl_port。

参数

struct cxl_port *port

引用此 dport 的 cxl_port。

struct device *dport_dev

表示 dport 的固件或 PCI 设备。

int port_id

解码器目标列表中的此 dport 的标识符。

resource_size_t rcrb

根复合体寄存器块的强制位置。

描述

请参阅 CXL 3.0 9.11.8 连接到 RCH 的 CXL 设备

int cxl_add_ep(struct cxl_dport *dport, struct device *ep_dev)¶

注册端点对端口的兴趣。

参数

struct cxl_dport *dport

路由到 ep_dev 的 dport。

struct device *ep_dev

表示端点的设备。

描述

根据端点的到达扫描中间 CXL 端口。当这些端点离开时,一旦所有关心该端口的端点都被移除,就可以销毁该端口。

int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld)¶

公共解码器设置/初始化。

参数

struct cxl_port *port

此解码器的所有者端口。

struct cxl_decoder *cxld

要初始化的公共解码器属性。

描述

一个端口可能包含一个或多个解码器。每个解码器都为 CXL.mem 利用率启用一些地址空间。解码器应由调用者配置,然后通过 cxl_decoder_add() 注册。

struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port, unsigned int nr_targets)¶

分配一个根级别的解码器。

参数

struct cxl_port *port

此解码器的所有者 CXL 根。

unsigned int nr_targets

下游目标的静态数量。

返回

要通过 cxl_decoder_add() 注册的新 cxl 解码器。“CXL 根”解码器是从 CXL 资源的顶级/静态平台固件描述解码为 CXL 标准解码拓扑的解码器。

struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port, unsigned int nr_targets)¶

分配一个交换机级别的解码器。

参数

struct cxl_port *port

此解码器的所有者 CXL 交换机端口。

unsigned int nr_targets

动态可寻址的下游目标的最大数量。

返回

要通过 cxl_decoder_add() 注册的新 cxl 解码器。“交换机”解码器是可以通过 PCIe 拓扑和 HDM 解码器功能枚举的任何解码器。这包括位于交换机上游端口/交换机下游端口和主机桥/根端口之间的解码器。

struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port)¶

分配一个端点解码器。

参数

struct cxl_port *port

此解码器的所有者端口。

返回

要通过 cxl_decoder_add() 注册的新 cxl 解码器。

int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map)¶

添加带有目标的解码器

参数

struct cxl_decoder *cxld

由 cxl_<类型>_decoder_alloc() 分配的 cxl 解码器

int *target_map

此解码器可以将内存流量定向到的下游端口列表。这些数字应与 PCIe 链路能力结构中的端口号相对应。

描述

某些类型的解码器可能没有任何目标。这方面的主要示例是端点设备。一个更尴尬的例子是热添加根端口的主桥(技术上可行,但不太可能)。

这是 cxl_decoder_add() 的锁定变体。

上下文

进程上下文。期望持有拥有 cxld 的端口的设备锁。

返回

如果解码器未正确配置,则返回负错误代码;否则

返回 0。

int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)¶

添加带有目标的解码器

参数

struct cxl_decoder *cxld

由 cxl_<类型>_decoder_alloc() 分配的 cxl 解码器

int *target_map

此解码器可以将内存流量定向到的下游端口列表。这些数字应与 PCIe 链路能力结构中的端口号相对应。

描述

这是 cxl_decoder_add_locked() 的解锁变体。请参阅 cxl_decoder_add_locked()。

上下文

进程上下文。获取并释放拥有 cxld 的端口的设备锁。

int __cxl_driver_register(struct cxl_driver *cxl_drv, struct module *owner, const char *modname)¶

为 cxl 总线注册驱动程序

参数

struct cxl_driver *cxl_drv

要附加的 cxl 驱动程序结构

struct module *owner

拥有的模块/驱动程序

const char *modname

父驱动程序的 KBUILD_MODNAME

int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, struct access_coordinate *coord)¶

检索存储在 CXL 路径的 dport 中的性能数据

参数

struct cxl_port *port

端点 cxl_port

struct access_coordinate *coord

输出性能数据

返回

失败时返回错误码,成功时返回 0。

Compute Express Link 协议分层在 PCIe 之上。CXL 核心为通过 PCIe 发生的 CXL 交互提供了一组助手。

int devm_cxl_port_enumerate_dports(struct cxl_port *port)¶

枚举上游端口的下游端口

参数

struct cxl_port *port

其 ->uport_dev 是要枚举的 dport 的上游的 cxl_port

描述

返回枚举的 dport 的正数或负错误代码。

int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, struct cxl_endpoint_dvsec_info *info)¶

为端点设置 HDM 解码

参数

struct cxl_dev_state *cxlds

设备状态

struct cxl_hdm *cxlhdm

映射的 HDM 解码器能力

struct cxl_endpoint_dvsec_info *info

缓存的 DVSEC 范围寄存器信息

描述

尝试启用端点的 HDM 解码器能力

void read_cdat_data(struct cxl_port *port)¶

读取此端口上的 CDAT 数据

参数

struct cxl_port *port

要从中读取数据的端口

描述

此调用将休眠等待来自 DOE 邮箱的响应。

void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)¶

在此 dport 上设置 CXL RAS 报告

参数

struct cxl_dport *dport

需要初始化的 cxl_dport

struct device *host

用于 devm 操作的主机设备。

long cxl_pci_get_latency(struct pci_dev *pdev)¶

计算 PCIe 链路的链路延迟

参数

struct pci_dev *pdev

PCI 设备

返回

计算的延迟,如果没有延迟则为 0

描述

CXL 内存设备软件指南 v1.0 2.11.4 链路延迟计算 链路延迟 = 链路传播延迟 + Flit 延迟 + 中继器延迟 链路传播延迟可以忽略不计,因此将使用 0 中继器延迟假设可以忽略不计,将使用 0 Flit 延迟 = Flit 大小 / 链路带宽 Flit 大小由规范定义。CXL rev3.0 4.2.1. 68B flit 用于高达 32GT/s。>32GT/s 时,使用 256B flit 大小。Flit 延迟转换为皮秒。

核心 CXL PMEM 基础设施支持持久内存供应,并充当 LIBNVDIMM 子系统的桥梁。如果平台固件至少通告一个支持持久内存的 CXL 窗口,则会在 CXL 设备拓扑的根部添加一个 CXL“桥”设备。该根级桥对应于 LIBNVDIMM“总线”设备。然后,对于 CXL 设备拓扑中的每个 cxl_memdev,都会添加一个桥设备来托管 LIBNVDIMM dimm 对象。注册这些桥时,会将本机 LIBNVDIMM uapi 转换为 CXL 操作,例如,命名空间标签访问命令。

CXL 设备功能通过 PCI DVSEC(指定供应商特定)和/或平台固件提供的描述符进行枚举。它们可以定义为一组,例如 CXL 第 8.1.12.2 节《内存设备 PCIe 能力和扩展能力》所要求的设备和组件寄存器,或者它们可以是附加到桥接和端点设备的单独功能。

为枚举和映射这些离散功能提供通用基础设施。

CXL 2.0 类型 3 内存设备邮箱的核心实现。该实现由 cxl_pci 驱动程序用于初始化设备并实现 cxl_mem.h IOCTL UAPI。它还实现了 LIBNVDIMM 的 cxl_pmem_ctl() 传输的后端。

CXL 区域¶

CXL 区域表示系统物理地址空间中映射的内存容量。CXL 根解码器标识潜在的 CXL 内存范围的边界,而区域表示通过主机桥、交换机和拓扑中的端点上的 HDM 解码器能力结构主动映射的容量。

区域配置有顺序约束。UUID 可以随时设置,但仅对持久区域可见。1. 交错粒度 2. 交错大小 3. 解码器目标

int cxl_port_attach_region(struct cxl_port *port, struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled, int pos)¶

通过端点跟踪区域在端口中的兴趣

参数

struct cxl_port *port

端口添加新的区域引用 'struct cxl_region_ref'

struct cxl_region *cxlr

要附加到 port 的区域

struct cxl_endpoint_decoder *cxled

用于创建或进一步固定区域引用的端点解码器

int pos

cxled 在 cxlr 中的交错位置

描述

附加事件是一个验证 CXL 解码设置约束并记录编程 HDM 解码器所需的元数据的机会,特别是解码器目标列表。

步骤如下:

  • 验证是否没有其他具有更高 HPA 且已与 port 关联的区域

  • 如果尚未存在,则建立区域引用

    • 此外,分配一个将在 port 上托管 cxlr 的解码器实例

  • 通过端点固定区域引用

  • 说明 port 的目标列表中需要多少个条目才能覆盖所有添加的端点。

int cxl_calc_interleave_pos(struct cxl_endpoint_decoder *cxled)¶

计算区域中的端点位置

参数

struct cxl_endpoint_decoder *cxled

给定区域的端点解码器成员

描述

端点位置是通过从端点到根解码器遍历拓扑结构并迭代应用此计算来计算的

position = position * parent_ways + parent_pos;

...其中 position 是从交换机和根解码器目标列表中推断出来的。

返回

成功时 position >= 0

失败时 -ENXIO

struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, int id, enum cxl_decoder_mode mode, enum cxl_decoder_type type)¶

向解码器添加区域

参数

struct cxl_root_decoder *cxlrd

根解码器

int id

要创建的 memregion id,或失败时为 memregion_free()

enum cxl_decoder_mode mode

此区域的端点解码器的模式

enum cxl_decoder_type type

选择此项是扩展器还是加速器(类型 2 或类型 3)

描述

这是区域初始化的第二步。区域存在于由 cxlrd 映射的地址空间中。

返回

如果区域已添加到 cxlrd,则为 0,否则返回负错误代码。该区域将命名为“regionZ”,其中 Z 是唯一的区域号。

int devm_cxl_add_pmem_region(struct cxl_region *cxlr)¶

添加一个 cxl_region 到 nd_region 的桥梁

参数

struct cxl_region *cxlr

此 pmem 区域桥设备 的父 CXL 区域

返回

成功时为 0,失败时为负错误代码。

外部接口¶

CXL IOCTL 接口¶

并非驱动程序支持的所有命令都始终可供用户空间使用。用户空间可以检查 QUERY 命令的结果以确定活动的命令集。或者,它可以发出命令并检查是否失败。

struct cxl_command_info¶

从查询返回的命令信息。

定义:

struct cxl_command_info {
    __u32 id;
    __u32 flags;
#define CXL_MEM_COMMAND_FLAG_MASK               GENMASK(1, 0);
#define CXL_MEM_COMMAND_FLAG_ENABLED            BIT(0);
#define CXL_MEM_COMMAND_FLAG_EXCLUSIVE          BIT(1);
    __u32 size_in;
    __u32 size_out;
};

成员

id

命令的 ID 号。

flags

指定命令行为的标志。

CXL_MEM_COMMAND_FLAG_USER_ENABLED

驱动程序支持给定的命令 id,并且设备上的相关操作码支持该命令。

CXL_MEM_COMMAND_FLAG_EXCLUSIVE

当内核主动拥有给定资源的管理权时,具有给定命令 id 的请求将以 EBUSY 终止。例如,当内核主动管理该空间时,无法写入标签存储区域。

size_in

预期输入大小,如果为可变长度则为 ~0。

size_out

预期输出大小,如果为可变长度则为 ~0。

描述

表示驱动程序和硬件都支持的单个命令。这是从查询 ioctl 返回的数组的一部分。以下是一个需要可变长度输入并返回 0 字节输出的命令。

  • id = 10

  • flags = CXL_MEM_COMMAND_FLAG_ENABLED

  • size_in = ~0

  • size_out = 0

请参阅 struct cxl_mem_query_commands。

struct cxl_mem_query_commands¶

查询支持的命令。

定义:

struct cxl_mem_query_commands {
    __u32 n_commands;
    __u32 rsvd;
    struct cxl_command_info __user commands[];
};

成员

n_commands

输入/输出参数。当 n_commands > 0 时,驱动程序将返回 min(num_support_commands, n_commands)。当 n_commands 为 0 时,驱动程序将返回支持的总命令数。

rsvd

保留供将来使用。

commands

支持的命令的输出数组。此数组必须由用户空间分配,至少为 min(num_support_commands, n_commands)

描述

允许用户空间查询驱动程序和硬件支持的可用命令。查询中不返回驱动程序或硬件不支持的命令。

示例

  • { .n_commands = 0 } // 获取支持的命令数

  • { .n_commands = 15, .commands = buf } // 返回前 15 个(或更少)支持的命令

请参见 struct cxl_command_info。

struct cxl_send_command¶

向内存设备发送命令。

定义:

struct cxl_send_command {
    __u32 id;
    __u32 flags;
    union {
        struct {
            __u16 opcode;
            __u16 rsvd;
        } raw;
        __u32 rsvd;
    };
    __u32 retval;
    struct {
        __u32 size;
        __u32 rsvd;
        __u64 payload;
    } in;
    struct {
        __u32 size;
        __u32 rsvd;
        __u64 payload;
    } out;
};

成员

id

要发送到内存设备的命令。这必须是查询命令返回的命令之一。

flags

命令的标志(输入)。

{unnamed_union}

匿名

raw

原始命令的特殊字段

raw.opcode

使用 RAW 命令时传递给硬件的操作码。

raw.rsvd

必须为零。

rsvd

必须为零。

retval

来自内存设备的返回值(输出)。

in

与输入有效负载关联的参数。

in.size

提供给设备的有效负载的大小(输入)。

in.rsvd

必须为零。

in.payload

指向有效负载输入内存的指针,有效负载为小端字节序。

out

与输出有效负载关联的参数。

out.size

从设备接收到的有效负载的大小(输入/输出)。此字段由用户空间填写,以告知驱动程序为输出分配了多少空间。它由驱动程序填充,以告知用户空间实际输出有效负载的大小。

out.rsvd

必须为零。

out.payload

指向有效负载输出内存的指针,有效负载为小端字节序。

描述

用户空间向硬件发送命令进行处理的机制。驱动程序将对命令大小进行基本验证。在某些情况下,甚至可能会内省有效负载。用户空间需要为 size_out 分配足够大的缓冲区,在某些情况下,该缓冲区长度可变。

©内核开发社区。| 由 Sphinx 5.3.0 & Alabaster 0.7.16 提供支持 | 页面源