Compute Express Link 驅動程式操作理論¶
Compute Express Link 記憶體裝置是一個實現 CXL.mem 協議的 CXL 元件。它包含一定量的易失性儲存器、永續性儲存器或兩者。它被列舉為 PCI 裝置,用於配置和透過 MMIO 郵箱傳遞訊息。它對系統物理地址空間的貢獻透過 HDM(主機管理裝置記憶體)解碼器處理,這些解碼器可以選擇性地定義裝置對主機橋下的多個裝置或跨主機橋交織的地址範圍的貢獻。
CXL 匯流排¶
類似於 RAID 驅動程式如何獲取磁碟物件並將它們組裝成新的邏輯裝置,CXL 子系統的任務是獲取 PCIe 和 ACPI 物件並將它們組裝成 CXL.mem 解碼拓撲。CXL.mem 拓撲的執行時配置需求也類似於 RAID,因為具有相同硬體配置的不同環境可能會決定以不同的方式組裝拓撲。一種方式可以選擇效能(RAID0),跨多個主機橋和端點進行記憶體條帶化,而另一種方式可以選擇容錯並停用 CXL.mem 拓撲中的任何條帶化。
平臺韌體在“CXL 根埠”(Linux 術語,表示 CXL 解碼拓撲的頂部)列舉一個交織選項選單。從那裡,PCIe 拓撲決定了哪些端點可以參與哪些主機橋解碼方案。根埠和端點之間的路徑中的每個 PCIe 交換機都引入了一個可以分割交織的點。例如,平臺韌體可能會說在給定的範圍內僅解碼到一個主機橋,但該主機橋可能會依次跨多個根埠交織週期。埠和端點之間的中間交換機可能會跨多個下游交換機埠交織週期,等等。
這是一個由“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"
}
}
]
}
]
}
]
}
在該列表中,每個“root”、“port”和“endpoint”物件對應一個核心“struct cxl_port”物件。“cxl_port”是一個可以將其後代解碼為 CXL.mem 的裝置。因此,“root”宣告非 PCIe 可列舉的平臺解碼範圍並將它們解碼為“ports”,“ports”解碼為“endpoints”,而“endpoints”表示從 SPA(系統物理地址)到 DPA(裝置物理地址)的解碼。
繼續 RAID 類比,磁碟既有拓撲元資料,也有裝置上的元資料,用於確定 RAID 集的組裝。CXL 埠拓撲和 CXL 埠連結狀態是 CXL.mem 集組裝的元資料。CXL 埠拓撲是透過 CXL.mem 裝置的到達來列舉的。也就是說,除非 PCIe 核心將 cxl_pci 驅動程式附加到 CXL 記憶體擴充套件器,否則 CXL 埠物件沒有任何作用。相反,對於熱插拔/移除場景,Linux PCI 核心不需要拆除交換機級別的 CXL 資源,因為 endpoint ->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<port_id>.<instance_id>”。
驅動程式基礎設施¶
本節介紹 CXL 記憶體裝置的驅動程式基礎設施。
CXL 記憶體裝置¶
這實現了 CXL 裝置由 Compute Express Link 規範定義的 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_mboxCXL 郵箱上下文
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;
u8 scrub_cycle;
int scrub_region_id;
void *err_rec_array;
};
成員
dev驅動程式核心裝置物件
cdev用於 ioctl 操作的字元裝置核心物件
cxlds支援此裝置的裝置狀態
detach_work活動 memdev 在其祖先中失去了一個埠
cxl_nvb如果存在 cxl_nvd,則協調移除
cxl_nvd如果裝置支援 pmem,則可選的 nvdimm 橋
endpoint此記憶體裝置與 CXL 埠拓撲的連線
id此 memdev 例項的 ID 號。
depth端點埠深度
scrub_cycle為此裝置設定的當前 scrub 週期
scrub_region_id為其設定當前 scrub 週期的支援區域的 ID 號(如果有)
err_rec_array儲存 memdev 錯誤記錄的 xarrays 列表,用於檢查記憶體修復操作的屬性是否來自當前啟動。
-
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_cmdsCEL 中啟用的所有中毒命令
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;
};
成員
statefw_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_cmdsCEL 中啟用的所有安全命令
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_rangeDPA 地址的範圍
coordQoS 效能資料(即延遲、頻寬)
cdat_coord來自 CDAT 的原始 QoS 效能資料
qos_classQoS 類 Cookie
-
struct cxl_dpa_partition¶
DPA 分割槽描述符
定義:
struct cxl_dpa_partition {
struct resource res;
struct cxl_dpa_perf perf;
enum cxl_partition_mode mode;
};
成員
resDPA 資源樹 (cxlds->dpa_res) 中分割槽的快捷方式
perf來自 CDAT 的分割槽的效能屬性
modeDPA 容量的操作模式,例如 ram、pmem、dynamic...
-
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 cxl_dpa_partition part[CXL_NR_PARTITIONS_MAX];
unsigned int nr_partitions;
u64 serial;
enum cxl_devtype type;
struct cxl_mailbox cxl_mbox;
#ifdef CONFIG_CXL_FEATURES;
struct cxl_features_state *cxlfs;
#endif;
};
成員
dev與此 CXL 狀態關聯的裝置
cxlmd表示 dev 的 CXL.mem 功能的裝置
reg_map元件和 ras 暫存器對映引數
regs已解析的暫存器塊
cxl_dvsecPCIe 裝置 DVSEC 的偏移量
rcd在 RCD 模式下執行 (CXL 3.0 9.11.8 連線到 RCH 的 CXL 裝置)
media_ready指示裝置介質是否可用
dpa_res裝置的整體 DPA 資源樹
partDPA 分割槽陣列
nr_partitionsDPA 分割槽數
serialPCIe 裝置序列號
type通用記憶體類裝置或供應商特定記憶體裝置
cxl_mboxCXL 郵箱上下文
cxlfsCXL 功能上下文
描述
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];
u64 total_bytes;
u64 volatile_only_bytes;
u64 persistent_only_bytes;
u64 partition_align_bytes;
u64 active_volatile_bytes;
u64 active_persistent_bytes;
struct cxl_event_state event;
struct cxl_poison_state poison;
struct cxl_security_state security;
struct cxl_fw_state fw;
struct notifier_block mce_notifier;
};
成員
cxlds跨 Type-2 和 Type-3 裝置的核心驅動程式狀態
lsa_size標籤儲存區域的大小 (CXL 2.0 8.2.9.5.1.1 識別記憶體裝置)
firmware_version記憶體裝置的韌體版本。
total_bytes所有可能容量的總和
volatile_only_bytes硬易失性容量
persistent_only_bytes硬永續性容量
partition_align_bytes可分割槽容量的對齊大小
active_volatile_bytes硬 + 軟易失性容量的總和
active_persistent_bytes硬 + 軟永續性容量的總和
event事件日誌驅動程式狀態
poison中毒驅動程式狀態資訊
security安全驅動程式狀態資訊
fw韌體上傳/啟用狀態
mce_notifierMCE 通知程式
描述
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);
};
成員
infoUAPI 中存在的命令資訊
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 Core¶
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參見 enum cxl_regloc_type
{unnamed_union}anonymous
component_map元件暫存器的 cxl_reg_map
device_map裝置暫存器的 cxl_reg_maps
pmu_mapCXL 效能監視單元的 cxl_reg_maps
-
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_dports 數量
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_state state;
int part;
int pos;
};
成員
cxld基本 cxl_decoder_object
dpa_res此解碼器主動宣告的 DPA 跨度
skipdpa_res 中的偏移量,其中對映 cxld.hpa_range
stateautodiscovery 狀態
part此解碼器對映的分割槽索引
poscxld.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_targetstarget 中的元素數量
target當前解碼器配置中的活動有序目標列表
描述
“switch”解碼器型別表示 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_classQoS 效能類 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;
resource_size_t cache_size;
};
成員
state允許驅動程式鎖定進一步的引數更改
uuid永續性區域的唯一 ID
interleave_ways區域中的端點數量
interleave_granularity每個端點對條帶的貢獻容量
res為此區域分配的 iomem 容量
targets當前解碼器配置中的活動有序目標
nr_targets目標數量
cache_size如果存在,則為擴充套件線性快取大小,否則為零。
描述
狀態轉換由 cxl_region_rwsem 保護
-
struct cxl_region¶
CXL 區域
定義:
struct cxl_region {
struct device dev;
int id;
enum cxl_partition_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 例項
endpointscxl_ep 例項,是此埠後代的端點
regionscxl_region_ref 例項,由此埠對映的區域
parent_dport指向父埠中的該埠的 dport
decoder_ida解碼器 ID 的分配器
reg_map元件和 ras 暫存器對映引數
nr_dportsdports 中的條目數
hdm_end跟蹤最後分配的 HDM 解碼器例項以進行分配排序
commit_end跟蹤最高提交解碼器的遊標以進行提交排序
dead已移除最後一個 ep,強制埠重新建立
depth此埠相對於根埠的深度。深度 0 為根埠。
cdat快取的 CDAT 資料
cdat_availablesysfs 中是否應提供 CDAT 屬性
pci_latency上游延遲(皮秒)
-
struct cxl_root¶
根 cxl_port 項的邏輯集合
定義:
struct cxl_root {
struct cxl_port port;
const struct cxl_root_ops *ops;
};
成員
portcxl_port 成員
opscxl 根操作
-
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;
int gpf_dvsec;
};
成員
dport_dev表示下游鏈路的 PCI 橋或韌體裝置
reg_map元件和 ras 暫存器對映引數
port_id解碼器目標列表中 dport 的唯一硬體識別符號
rcrb有關根複合體暫存器塊佈局的資料
rch指示此 dport 是在 RCH 模式還是 VH 模式下列舉的
port對包含此下游埠的 cxl_port 的引用
regs已解析的 Dport 暫存器塊
coord訪問座標(頻寬和延遲效能屬性)
link_latency計算的 PCIe 下游延遲
gpf_dvsec快取的 GPF 埠 DVSEC
-
struct cxl_ep¶
跟蹤端點對埠的興趣
定義:
struct cxl_ep {
struct device *ep;
struct cxl_dport *dport;
struct cxl_port *next;
};
成員
ep託管通用 CXL 端點(擴充套件器或加速器)的裝置
dport哪個 dport 在 port 上路由到此端點
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_epsport 下方的端點數
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_rangeDVSEC 中範圍的快取屬性,PCIE_DEVICE
-
int add_cxl_resources(struct resource *cxl_res)¶
在 iomem_resource 中反映 CXL 固定記憶體視窗
引數
struct resource *cxl_res一個獨立的資源樹,其中每個 CXL 視窗都是同級視窗
描述
遍歷 cxl_res 中的每個 CXL 視窗,並將其新增到 iomem_resource,可能會擴充套件其邊界以確保任何衝突的資源都成為子資源。如果視窗被擴充套件,則它可能與另一個視窗條目衝突,並需要截斷或修剪視窗。考慮這種情況
|-- "CXL Window 0" --||----- "CXL Window 1" -----|
|--------------- "System RAM" -------------|
...其中平臺韌體已在 2 個視窗中建立為系統 RAM 資源,但已將視窗 1 的某些部分留用於動態 CXL 區域配置。在這種情況下,“視窗 0”將跨越整個“系統 RAM”跨度,而“CXL 視窗 1”將被截斷到該“系統 RAM”資源末尾之後的剩餘尾部。
Compute Express Link Host Managed Device Memory(主機託管裝置記憶體),從 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 request_skip(struct cxl_dev_state *cxlds, struct cxl_endpoint_decoder *cxled, const resource_size_t skip_base, const resource_size_t skip_len)¶
在 cxlds->dpa_res 資源樹中跟蹤 DPA“跳過”
引數
struct cxl_dev_state *cxldsCXL.mem 裝置上下文,它是 cxled 的父級
struct cxl_endpoint_decoder *cxled端點解碼器建立跳過較低 DPA 的新分配
const resource_size_t skip_baseDPA < 新 DPA 分配的開始(DPAnew)
const resource_size_t skip_lenskip_base + skip_len == DPAnew
描述
相對於多個分割槽中的可用容量,DPA“跳過”源自亂序 DPA 分配事件。這是一個浪費的事件,因為可用的 DPA 被丟棄,但如果部署有例如雙 RAM+PMEM 裝置,想要使用 PMEM,並且有未分配的 RAM DPA,則必須犧牲空閒 RAM DPA 才能開始分配 PMEM。有關更多詳細資訊,請參閱 CXL 3.1 8.2.4.19.13 “解碼器保護”中的第三個“實現說明”。
“跳過”始終覆蓋先前分割槽中最後分配的 DPA 到當前分割槽要分配的開始。分配永遠不會在分割槽的中間開始,並且分配始終以相反的順序解除分配(請參閱 cxl_dpa_free(),或來自強制按順序分配的自然 devm 展開順序)。
如果保證 cxlds->nr_partitions <= 2,則“跳過”將始終包含在單個分割槽中。鑑於 cxlds->nr_partitions 可能 > 2,這會導致“跳過”可能跨越“partition[0] 的尾部容量,partition[1] 的全部,...,partition[N-1] 的全部”以支援從 partition[N] 進行分配的情況。反過來,這與 cxlds->dpa_res 中的分割槽“struct resource”邊界互動,從而需要按分區劃分“跳過”請求。也就是說,這是使用“struct resource”樹來檢測範圍衝突,同時也在 cxlds->dpa_res 中跟蹤分割槽邊界的怪癖。
-
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 *outc1 和 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
描述
收集聚合的端點頻寬,並將頻寬儲存在 xarray 中,該 xarray 由交換機的上游裝置或 RP 裝置索引。每個端點都包含來自端點 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 根的布林值。
返回
- 每個父交換機或根埠的 resulting cxl_perf_ctx 的 xarray
或 ERR_PTR(-errno)
描述
迭代 xarray。獲取下游計算頻寬、上游鏈路頻寬和上游交換機(如果存在)的 SSLBIS 的最小值。對交換機上游裝置或 RP 裝置下的結果頻寬求和。如果存在多個交換機,則可以對該函式進行多次迭代。
引數
struct xarray *xa儲存 cxl_perf_ctx 的 xarray,該 cxl_perf_ctx 具有每個根埠裝置下方計算的頻寬。
返回
儲存每個主機橋的 cxl_perf_ctx 的 xarray 或 ERR_PTR(-errno)
引數
struct xarray *xa儲存 cxl_perf_ctx 的 xarray,該 cxl_perf_ctx 具有每個主機橋下方計算的頻寬。
返回
儲存每個 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_xaXarray 儲存每個 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 *hostdevm 操作的主機裝置
struct device *uport_dev實現此上游埠的“物理”裝置
resource_size_t component_reg_phys(可選)用於可配置的 cxl_port 例項
struct cxl_dport *parent_dportCXL 記憶體解碼層次結構中的下一跳
-
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_physCXL 元件暫存器的可選位置
描述
請注意,dports 會附加到埠主機(對於根埠)或埠本身(對於交換機埠)的 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輸出效能資料
返回
失敗時返回 errno,成功時返回 0。
Compute Express Link 協議分層在 PCIe 之上。CXL 核心為 CXL 互動提供了一組助手函式,這些互動透過 PCIe 發生。
引數
struct cxl_port *portcxl_port,其 ->uport_dev 是要列舉的 dport 的上游
描述
返回列舉的 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 *hostdevm 操作的主機裝置
-
long cxl_pci_get_latency(struct pci_dev *pdev)¶
計算 PCIe 鏈路的鏈路延遲
引數
struct pci_dev *pdevPCI 裝置
返回
計算出的延遲或 0(無延遲)
描述
CXL 記憶體裝置 SW 指南 v1.0 2.11.4 鏈路延遲計算 鏈路延遲 = 鏈路傳播延遲 + Flit 延遲 + Retimer 延遲 LinkProgationLatency 可以忽略不計,因此將使用 0 RetimerLatency 假定可以忽略不計,因此將使用 0 FlitLatency = FlitSize / LinkBandwidth FlitSize 由規範定義。CXL rev3.0 4.2.1。 68B flit 用於高達 32GT/s。 >32GT/s,使用 256B flit 大小。 FlitLatency 轉換為皮秒。
核心 CXL PMEM 基礎設施支援永續性記憶體配置,並充當與 LIBNVDIMM 子系統的橋樑。如果平臺韌體至少通告一個支援永續性記憶體的 CXL 視窗,則會在 CXL 裝置拓撲的根新增一個 CXL“橋”裝置。該根級別橋對應於 LIBNVDIMM “匯流排”裝置。然後,對於 CXL 裝置拓撲中的每個 cxl_memdev,都會新增一個橋裝置來託管 LIBNVDIMM dimm 物件。當這些橋註冊時,原生 LIBNVDIMM uapi 會轉換為 CXL 操作,例如,名稱空間標籤訪問命令。
引數
struct cxl_port *port與 nvdimm-bridge 關聯的 root-cxl-port 的任何後代埠
-
struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host, struct cxl_port *port)¶
新增 LIBNVDIMM 拓撲的根
引數
struct device *host平臺韌體根裝置
struct cxl_port *portCXL 拓撲根目錄的 CXL 埠
返回
可以託管 cxl_nvdimm 物件的橋裝置
-
int devm_cxl_add_nvdimm(struct cxl_port *parent_port, struct cxl_memdev *cxlmd)¶
在 cxl_memdev 和 nvdimm 之間新增橋樑
引數
struct cxl_port *parent_port(要新增的)cxlmd 端點埠的父埠
struct cxl_memdev *cxlmd將執行 LIBNVDIMM 操作的 cxl_memdev 例項
返回
成功時返回 0,失敗時返回負錯誤程式碼。
CXL 裝置功能由 PCI DVSEC(指定供應商特定)和/或平臺韌體提供的描述符列舉。 它們可以定義為一組,例如 CXL 第 8.1.12.2 節記憶體裝置 PCIe 功能和擴充套件功能授權的裝置和元件暫存器,或者它們可以是附加到橋接和端點裝置的單個功能。
提供用於列舉和對映這些離散功能的通用基礎設施。
-
void cxl_probe_component_regs(struct device *dev, void __iomem *base, struct cxl_component_reg_map *map)¶
檢測 CXL 元件暫存器塊
引數
struct device *devbase 對映的主機裝置
void __iomem *base包含 HDM 解碼器功能標頭的對映
struct cxl_component_reg_map *map描述找到的暫存器塊資訊的對映物件
描述
請參閱 CXL 2.0 8.2.4 元件暫存器佈局和定義 請參閱 CXL 2.0 8.2.5.5 CXL 裝置暫存器介面
探測元件暫存器資訊並在對映物件中返回它。
-
void cxl_probe_device_regs(struct device *dev, void __iomem *base, struct cxl_device_reg_map *map)¶
檢測 CXL 裝置暫存器塊
引數
struct device *devbase 對映的主機裝置
void __iomem *baseCXL 2.0 8.2.8 CXL 裝置暫存器介面的對映
struct cxl_device_reg_map *map描述找到的暫存器塊資訊的對映物件
描述
探測裝置暫存器資訊並在對映物件中返回它。
-
int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type, struct cxl_register_map *map, unsigned int index)¶
按型別/索引查詢暫存器塊
引數
struct pci_dev *pdev要列舉的 CXL PCI 裝置。
enum cxl_regloc_type type暫存器塊指示器 id
struct cxl_register_map *map列舉輸出,錯誤時被破壞
unsigned int index暫存器定位器 DVSEC 中找到的所需 regblock 的特定例項的索引。
返回
如果暫存器塊已列舉,則為 0;否則為負錯誤程式碼
描述
CXL DVSEC 可能會指向一個或多個暫存器塊,按 type 和 index 搜尋它們。
-
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, struct cxl_register_map *map)¶
按型別查詢暫存器塊
引數
struct pci_dev *pdev要列舉的 CXL PCI 裝置。
enum cxl_regloc_type type暫存器塊指示器 id
struct cxl_register_map *map列舉輸出,錯誤時被破壞
返回
如果暫存器塊已列舉,則為 0;否則為負錯誤程式碼
描述
CXL DVSEC 可能會指向一個或多個暫存器塊,按 type 搜尋它們。
-
int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)¶
計算給定 regblock 型別的例項。
引數
struct pci_dev *pdev要列舉的 CXL PCI 裝置。
enum cxl_regloc_type type暫存器塊指示器 id
描述
某些 regblock 可能會重複。 計算有多少個例項。
返回
匹配 regblock 的非負計數,否則為負錯誤程式碼。
CXL 2.0 Type-3 記憶體裝置郵箱的核心實現。 該實現由 cxl_pci 驅動程式用於初始化裝置並實現 cxl_mem.h IOCTL UAPI。 它還實現了用於 LIBNVDIMM 的 cxl_pmem_ctl() 傳輸的後端。
-
int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *mbox_cmd)¶
核心內部介面,用於傳送郵箱命令
引數
struct cxl_mailbox *cxl_mboxCXL 郵箱上下文
struct cxl_mbox_cmd *mbox_cmd要執行的已初始化命令
上下文
任何上下文。
返回
%>=0 - 在 out 中返回的位元組數。
-E2BIG- 有效負載對於硬體來說太大。
-EBUSY- 無法獲得獨佔郵箱訪問許可權。
-EFAULT- 發生硬體錯誤。
-ENXIO- 命令已完成,但裝置報告了錯誤。
-EIO- 意外的輸出大小。
描述
郵箱命令可能會成功執行,但裝置本身報告了錯誤。 雖然這種區別對於來自使用者空間的命令可能很有用,但核心只能在兩者都成功時使用結果。
-
bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)¶
檢查 in_payload 的內容。
引數
u16 opcode郵箱命令操作碼。
void *payload_in指向從使用者空間傳入的輸入有效負載的指標。
返回
true - payload_in 通過了 opcode 的檢查。
false - payload_in 包含無效或不支援的值。
描述
驅動程式可能會在將來自使用者空間的郵箱命令傳送到裝置之前檢查有效負載內容。 其目的是拒絕具有已知不安全的輸入有效負載的命令。 此檢查並非旨在取代使用者對郵箱命令引數的仔細選擇,也不保證使用者命令會成功或適當。
特定檢查由操作碼確定。
-
int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, struct cxl_mailbox *cxl_mbox, const struct cxl_send_command *send_cmd)¶
檢查 CXL_MEM_SEND_COMMAND 的欄位。
引數
struct cxl_mbox_cmd *mbox_cmd已清理和填充的
struct cxl_mbox_cmd。struct cxl_mailbox *cxl_mboxCXL 郵箱上下文
const struct cxl_send_command *send_cmd從使用者空間複製的
struct cxl_send_command。
返回
0- out_cmd 準備好傳送。
-ENOTTY- 指定了無效命令。
-EINVAL- 使用了保留欄位或無效值。
-ENOMEM- 輸入或輸出緩衝區大小不正確。
-EPERM- 嘗試使用受保護的命令。
-EBUSY- 核心已宣告對此操作碼的獨佔訪問許可權
描述
此命令的結果是 mbox_cmd 中完全驗證的命令,可以安全地傳送到硬體。
-
int handle_mailbox_cmd_from_user(struct cxl_mailbox *cxl_mbox, struct cxl_mbox_cmd *mbox_cmd, u64 out_payload, s32 *size_out, u32 *retval)¶
為使用者空間分派郵箱命令。
引數
struct cxl_mailbox *cxl_mbox操作的郵箱上下文。
struct cxl_mbox_cmd *mbox_cmd經過驗證的郵箱命令。
u64 out_payload指向使用者空間的輸出有效負載的指標。
s32 *size_out(輸入)要複製出的最大有效負載大小。(輸出)硬體生成的有效負載大小。
u32 *retval來自操作的硬體生成的返回程式碼。
返回
0- 郵箱事務成功。 這意味著郵箱協議已成功完成,而不是操作本身成功。
-ENOMEM- 無法分配反彈緩衝區。
-EFAULT- copy_to/from_user 發生了某些情況。
-EINTR- 郵箱獲取中斷。
-EXXX- 事務級別故障。
描述
代表使用者空間請求分派郵箱命令。 輸出有效負載已複製到使用者空間。
請參閱 cxl_send_cmd()。
-
void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)¶
遍歷命令效果日誌。
引數
struct cxl_memdev_state *mds操作的驅動程式資料
size_t size命令效果日誌的長度。
u8 *celCEL
描述
迭代 CEL 中的每個條目,並確定驅動程式是否支援該命令。 如果是,則該命令已為裝置啟用,並且可以在以後使用。
-
int cxl_enumerate_cmds(struct cxl_memdev_state *mds)¶
列舉裝置的命令。
引數
struct cxl_memdev_state *mds操作的驅動程式資料
描述
如果列舉成功完成,則返回 0。
CXL 裝置可選地支援某些命令。 此函式將確定硬體支援的命令集,並更新 mds 中的 enabled_cmds 點陣圖。
-
void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status)¶
從裝置獲取事件記錄
引數
struct cxl_memdev_state *mds操作的驅動程式資料
u32 status事件狀態暫存器值,用於標識哪些事件可用。
描述
檢索裝置上所有可用的事件記錄,將其報告為跟蹤事件,並清除它們。
請參閱 CXL rev 3.0 8.2.9.2.2 獲取事件記錄 請參閱 CXL rev 3.0 8.2.9.2.3 清除事件記錄
-
int cxl_mem_get_partition_info(struct cxl_memdev_state *mds)¶
獲取分割槽資訊
引數
struct cxl_memdev_state *mds操作的驅動程式資料
描述
檢索指定裝置的當前分割槽資訊。 活動值是以位元組為單位的當前容量。 如果不為 0,“next”值是以位元組為單位的待定值,將在下次冷復位時生效。
請參閱 CXL 8.2.9.5.2.1 獲取分割槽資訊
返回
如果沒有錯誤,則返回 0;否則返回郵箱命令的結果。
-
int cxl_dev_state_identify(struct cxl_memdev_state *mds)¶
將 IDENTIFY 命令傳送到裝置。
引數
struct cxl_memdev_state *mds操作的驅動程式資料
返回
如果 identify 已成功執行或介質未準備好,則返回 0。
描述
這會將 identify 命令分派到裝置,並在成功時填充要匯出到 sysfs 的結構。
-
int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)¶
將清理命令傳送到裝置。
引數
struct cxl_memdev *cxlmd操作的裝置
u16 cmd特定的清理命令操作碼
返回
如果命令已成功執行,則返回 0,無論實際的安全操作是否在後臺完成,例如對於清理的情況。 錯誤返回值可能是郵箱命令的結果,如果不滿足安全要求或上下文無效,則為 -EINVAL;如果清理操作已經在進行中,則為 -EBUSY。
描述
請參閱 CXL 3.0 8.2.9.8.5.1 清理和 8.2.9.8.5.2 安全擦除。
CXL 功能:包括郵箱的 CXL 裝置支援允許列出、獲取和設定可選定義的功能的命令,例如記憶體備用或後封裝備用。 供應商可以為裝置定義自定義功能。
有關 API 詳細資訊,請參閱 devm_cxl_setup_features()。
CXL 區域¶
CXL 區域表示系統物理地址空間中對映的記憶體容量。 雖然 CXL 根解碼器標識潛在 CXL 記憶體範圍的邊界,但區域表示主機橋、交換機和拓撲中端點的 HDM 解碼器功能結構對映的活動容量。
區域配置具有排序約束。 UUID 可以隨時設定,但僅對永續性區域可見。 1. 交錯粒度 2. 交錯大小 3. 解碼器目標
-
struct cxl_decoder *cxl_port_pick_region_decoder(struct cxl_port *port, struct cxl_endpoint_decoder *cxled, struct cxl_region *cxlr)¶
為區域分配或查詢解碼器
引數
struct cxl_port *portcxled 暗示的端點的祖先埠
struct cxl_endpoint_decoder *cxled要由 port 對映或當前對映的端點解碼器
struct cxl_region *cxlr要建立或驗證解碼 port 的區域
描述
在區域建立路徑中,cxl_port_pick_region_decoder() 是一個分配器,用於查詢空閒埠。 在區域組裝路徑中,它是呼叫平臺韌體選擇的解碼器以用於驗證目的。
結果記錄在 port 中的 'struct cxl_region_ref' 中。
-
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 poscxled 在 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_partition_mode mode, enum cxl_decoder_type type)¶
向解碼器新增區域
引數
struct cxl_root_decoder *cxlrd根解碼器
int id要建立的 memregion id,或失敗時 memregion_free()
enum cxl_partition_mode mode此區域的端點解碼器的模式
enum cxl_decoder_type type選擇這是擴充套件器還是加速器(type-2 或 type-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}anonymous
raw原始命令的特殊欄位
raw.opcode使用 RAW 命令時傳遞給硬體的操作碼。
raw.rsvd必須為零。
rsvd必須為零。
retval來自記憶體裝置的返回值(輸出)。
in與輸入有效負載關聯的引數。
in.size提供給裝置的有效負載的大小(輸入)。
in.rsvd必須為零。
in.payload指向有效負載輸入的記憶體的指標,有效負載是小端位元組序。
out與輸出有效負載關聯的引數。
out.size從裝置接收的有效負載的大小(輸入/輸出)。此欄位由使用者空間填寫,以告知驅動程式為輸出分配了多少空間。它由驅動程式填充,以使使用者空間知道實際的輸出有效負載有多大。
out.rsvd必須為零。
out.payload指向有效負載輸出的記憶體的指標,有效負載是小端位元組序。
描述
使用者空間向硬體傳送命令進行處理的機制。驅動程式將對命令大小進行基本驗證。在某些情況下,甚至可能會檢查有效負載。使用者空間需要為 size_out 分配足夠大的緩衝區,在某些情況下,size_out 的長度可能可變。