计算快线链路内存设备¶
计算快线链路内存设备是实现 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_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 *xa
保存 cxl_perf_ctx 的 xarray,该结构具有在每个根端口设备下方计算的带宽。
返回
保存每个主机桥的 cxl_perf_ctx 的 xarray 或 ERR_PTR(-errno)
参数
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
重新计算区域的带宽
参数
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 设备
参数
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)¶
分配一个端点解码器。
-
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 交互提供了一组助手。
参数
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 解码器能力
参数
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_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 分配足够大的缓冲区,在某些情况下,该缓冲区长度可变。