CXL (Compute Express Link) その14 - InterleaveとCXL.ioコマンド: Capacity Config and Label Storage

私はメモリデバイスの不揮発性メモリ制御やホストIFなどを扱うソフト屋をやっております。
仕事でCXL(Compute Express Link)まわりの技術に関わっています。
CXL技術に関連するメモ書きを残していこうと思います。
ホストのCPUとOS/Applicationまわりの経験・知識共に乏しいので、親切な方は教えて下さると幸いです。
また、間違い、アドバイス、その他、ご意見やご要望ありましたらお気軽にどうぞ。

---
CXLメモリデバイスのInterleaveについてと、Interleaveの構成情報の設定と取得コマンドについて書きます。

# 1. Link Topology
CXLの仕様では、1つのホストCPUに対して複数のCXLメモリデバイスを並列に接続し、Interleaveして使用するユースケースがカバーされています。下図に、CXLメモリデバイスをInterleaveで接続した例を示します。
![Interleave.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292852/0def9908-906b-6f35-e41a-d0fbf47bb342.png)

上図に示す例は、ホストCPUはSwitchを挟んで8台のCXLメモリデバイスを並列に接続し、Interleave Granularityを256Bとして、Interleaveして構成した例です。

ホストCPUは、各デバイスのメモリ空間に対して、HPA (Host Physical Address)を割り当て、HPAを指定してデータの書き込みと読み出しを行います。上図に示す例では、HPAが0000h-00FFhがDevice 0、HPAが0100h-01FFhがDevice 1の割り当てとしています。

CXLメモリデバイスは、ホストCPUから指定されたHPAを、自分が持つメモリ空間のアドレス(DPA: Device Physical Address)に変換してデータの書き込みと読み出しを行います。上図に示す例では、Device 1は、HPAの0100h-01FFhをDPAの0000h-00FFh、HPAの0900h-09FFhをDPAの0100h-01FFhと割り当てています。
HPAとDPAとの紐づけを行うための情報として、CXLメモリデバイスのレジスタには、Interleave GranularityとInterleaveのWay数が、ホストCPUにより設定されます。上図に示す例では、各CXLメモリデバイスの該当するレジスタに、Interleave Granularity=256B、Way=8が設定されます。

設定可能なInterleave Granularityは、CXLメモリデバイスの製品により異なりますが、CXLの仕様では最小サイズを256Bとし、512B、1kB、2kB、…、16kBまで設定可能としています。
設定可能なWay数は、CXLメモリデバイスの製品により異なりますが、CXL2.0の仕様では1、2、4、8が設定可能、CXL3.0の仕様では3、6、12、16が追加される見込みです。


# 2. Capacity Config and Label Storage Command Set

CXLメモリデバイスのレジスタに設定されるInterleaveの構成情報は揮発性の扱いですが、ホストシステムはInterleaveの構成情報をCXLメモリデバイスの専用の不揮発性メモリに記録することも可能です。Interleaveの構成情報を、CXLメモリデバイスの専用の不揮発性メモリに記録するためのコマンドセットが、Capacity Config and Label Storageコマンドセットです。

Interleaveの構成情報等を設定するためのCXLメモリデバイスの領域は、Label Storage Area (LSA)としてCXLの仕様で定められ、不揮発の領域として扱われます。
LSAに設定するデータのフォーマットは、CXLの仕様で決められていますが、CXLメモリデバイスがLSAのデータを解釈して使うことはありません。LSAに設定されたInterleaveの構成情報は、システムの電源断からの再起動後に電源断前の構成情報を取得する等の用途で、ホストシステムが解釈して使用します。

Capacity Config and Label Storageコマンドセットには、下表に示す4つのコマンドが定義されています。
| Command | Required | 概要 |
|:--|:-:|:--|
| Get Partition Info | O | 設定したパーティション情報を取得する。 |
| Set Partition Info | O | パーティション情報を設定する。 |
| Get LSA | PM | Label LSAのデータを取得する。 |
| Set LSA | PM | Label LSAにデータを設定する。 |

Interleaveの構成情報の他に、ホストシステムがCXLメモリデバイスに設定したパーティションの情報も扱うことができます。ただし、ここでいうパーティションの意味は、ストレージで使われるパーティションの意味とは異なります。
パーティションで区分けされるのは、ホストが、記録したデータを揮発性データとして扱う領域と、不揮発性データとして扱う領域です。

Set Partition Infoでは、CXLメモリデバイスのメモリ領域の内、ホストシステムが記録したデータを揮発性データとして扱う領域のサイズを指定することができます。揮発性データとして扱うとは、CXLメモリデバイスの電源を切り、再度CXLメモリデバイスの電源を入れた場合に、電源を切る前にCXLメモリデバイスの記録したデータを再利用しないということを意味します。

## 2.1 Label Storage Area (LSA)

CXLの仕様では、LSAに設定可能なデータのフォーマットとして、下表に示す2種類のLabelが定められています。
| Label | 概要 |
|:--|:--|
| Region Label | Interleaveの構成情報を設定する。 |
| Namespace Label | Namespaceの情報を設定する。 |

Region LabelとNamespace Labelは、256Bを1つの単位(Slot)として、LSAに複数設定することができます。

### 2.1.1 Region Label
Region Labelのフォーマットを下図に示します。
![RegionLabel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292852/d4f473f2-e6cf-1592-94ff-081f9e9e63bf.png)
それぞれのパラメータを下表に示します。
| Field | Length | 概要 |
|:--|--:|:--|
| Type | 10h | Region Labelを示すID。|
| UUID | 10h | RFC4122で定められるUUID。 |
| Flags | 04h | Label更新中の場合は 00000008hが入る。それ以外は00000000h。 |
| N Label | 02h | InterleaveのWay数。 |
| Position | 02h | Interleaveを構成するデバイス内での位置情報。 |
| DPA | 08h | Interleaveで使用する領域の先頭DPA。 |
| Row Size | 08h | Interleaveで使用する領域のサイズ。 |
| HPA | 08h | Interleaveで使用する領域の先頭HPA。 |
| Slot | 04h | このLabelに付けたIndex。 |
| Interleave Granularity | 04h | Interleave Granularity。 |
| Alignment | 04h | Interleaveに割り当てた領域のアラインメント。 |
| CheckSum | 08h | このLabelのチェックサム。 |

Interleaveで使用する場合、組み合わせて使用される他のCXLメモリデバイスLabelを全て更新する必要があるため、全てのLabelの更新が完了するまで、一時的にFlagは00000008hで更新します。全てのCXLメモリデバイスのLabelが更新が終わると、Flagは00000000hで更新します。このFlagにより、他のCXLメモリデバイスのLabel更新中に、停電等でCXLメモリデバイスの電源が切れてしまった場合でも、どの状態で電源が切れてしまったかが検出できます。

### 2.1.2 Namespace Label
Namespace Labelを下図に示します。Namespace Labelでは、並列に接続したCXLメモリデバイスの領域をNamespaceとして扱うためのパラメータを扱います。
![NamespaceLabel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292852/4e2106d6-fd58-65c1-5bf9-ad14c80bd3e1.png)
それぞれのパラメータを下表に示します。
| Field | Length | 概要 |
|:--|--:|:--|
| Type | 10h | Namespace Labelを示すID。|
| UUID | 10h | RFC4122で定められるUUID。 |
| Name | 40h | Namespaceに付けた名前。 |
| Flags | 04h | Label更新中の場合は 00000008hが入る。それ以外は00000000h。 |
| N Range | 02h | Namespaceに割り当てたメモリ領域の数。不連続なメモリ領域を同一のNamespaceに割り当てた場合に使用される。 |
| Position | 02h | Interleaveを構成するデバイス内での位置情報。 |
| DPA | 08h | Interleaveで使用する領域の先頭DPA。 |
| Row Size | 08h | Interleaveで使用する領域のサイズ。 |
| Slot | 04h | このLabelに付けたIndex。 |
| Alignment | 04h | Interleaveに割り当てた領域のアラインメント。 |
| Region UUID | 10h | このNamespaceと紐づけられるRegion LabelのUUID。 |
| Address Abstraction UUID | 10h | このNamespaceで使われるAddress abstraction。使用方法はCXLの仕様範囲外。 |
| LBA Size | 02h | NamespaceのLBAのサイズ。 |
| CheckSum | 08h | このLabelのチェックサム。 |

## 2.2 コマンドパラメータ
Capacity Config and Label Storageコマンドセットで定義されるコマンドの詳細を示します。
コマンドで指定するパラメータをInput Payload、応答として返されるパラメータをOutput Payloadで記載します。

### 2.2.1 Get Partition Info
Get Partition Infoでは、CXLメモリデバイスに設定されたパーティションの情報を取得します。

**Output Payload**
| Byte Offset | Length | 概要 |
|--:|--:|:--|
| 0 | 8 | Active Volatile Capacity: 有効である揮発性データとして扱うメモリ領域のサイズ。|
| 8 | 8 | Active Persistent Capacity: 有効である不揮発性データとして扱うメモリ領域のサイズ。|
| 16 | 8 | Next VolatileCapacity: CXLメモリデバイスのリセット後、有効となる揮発性データとして扱うメモリ領域のサイズ。|
| 24 | 8 | Next VolatileCapacity: CXLメモリデバイスのリセット後、有効となる不揮発性データとして扱うメモリ領域のサイズ。|

### 2.2.2 Set Partition Info
Set Partition Infoでは、CXLメモリデバイスにパーティションの情報を設定します。

**Input Payload**

| Byte Offset | Length | 概要 |
|--:|--:|:--|
| 0 | 8 | Volatile Capacity: 揮発性データとして扱うメモリ領域のサイズ。|
| 8 | 1 | Flags: 設定したVolatile Capacityを有効にするタイミングを示す。<br>　Bit[0]: 1を設定することでVolatile Capacityの設定直後に適用することを通知する。0を設定した場合、CXLメモリデバイスのリセット後から適用する。|

### 2.2.3 Get LSA
Get LSAではLSAに設定したデータを取得します。

**Input Payload**

| Byte Offset | Length | 概要 |
|--:|--:|:--|
| 0 | 4 | Offset: LSAの先頭からのオフセット。|
| 4 | 4 | Length: 取得するLSAのデータのサイズ。|

**Output Payload**

| Byte Offset | Length | 概要 |
|--:|--:|:--|
| 0 | Varies | Data: LSAのデータ(Labelのデータ)。|

### 2.2.4 Set LSA
Set LSAではLSAにデータを設定します。

**Input Payload**

| Byte Offset | Length | 概要 |
|--:|--:|:--|
| 0 | 4 | Offset: LSAの先頭からのオフセット。|
| 4 | 4 | Reserved。|
| 8 | Varies | Data: LSAに設定するデータ(Labelのデータ)。|

----