본문으로 건너뛰기
CXL 4.0 Internals · 8/15

Ch 8: CXL.mem — M2S·S2M·HDM Decoder

· Hawk · 9분 읽기

#한 줄 요약

“CXL.mem은 host CPU의 load·store instruction이 64 B cache line 단위로 변환되어 PCIe 링크 위를 흐르는 프로토콜입니다.”M2S Req·RwD가 명령을, S2M NDR·DRS가 응답을 전달합니다. HDM Decodersystem physical address → device physical address 매핑을 담당하고, Tag 기반 out-of-order completion으로 queue 활용을 극대화합니다.

Ch 7에서 디바이스가 host memory를 cache하는 CXL.cache를 봤습니다. 이 장은 반대 방향host가 device memory를 load/store하는 CXL.mem입니다.

#CXL.mem의 매력 — Native load/store

CPU의 load instruction (mov rax, [0x12345000])이 device memory에 직접 도달합니다:

단계처리
1CPU 명령 — mov rax, [VA]
2MMU가 VA → PA 변환
3메모리 컨트롤러가 DDR 또는 CXL Root Port로 분기 (HDM Decoder)
4CXL Root Port → CXL link → CXL device
5Device가 DRAM read (64 B cache line)
6Device → host로 응답
7CPU가 데이터 받음, load 완료

드라이버 호출 없음. DMA setup 없음. NVMe SSD와는 완전히 다른 의미입니다.

이게 가능한 이유는 호스트의 메모리 컨트롤러가 CXL Root Port를 DDR DIMM과 같은 등급으로 취급하기 때문입니다.

#4가지 메시지 채널

CXL.mem 트랜잭션은 두 방향·각 두 채널입니다.

방향채널메시지의미
Host → DeviceM2S ReqMemRd·MemRdData·MemInvhost의 read·invalidate 요청
Host → DeviceM2S RwDMemWr·MemWrPtlhost의 write 요청 + data
Device → HostS2M NDRCmp·Cmp-S·Cmp-E·Cmp-Mno-data response (write 완료·invalidate 완료)
Device → HostS2M DRSMemDatadata response (read 결과 64 B)
Device → HostS2M BISnpBISnpBack-Invalidation Snoop (HDM-DB only)

기본은 M2S Req → S2M DRS (read) 또는 M2S RwD → S2M NDR (write). BISnp는 Type 2 HDM-DB만.

#Read 트랜잭션 흐름

가장 단순한 load 동작:

단계동작
1CPU 명령: mov rax, [0x12345000]
2MMU가 VA → PA 변환 (예: 0x80000000)
3HDM Decoder가 PA를 CXL device로 라우팅
4Host → Device: M2S Req MemRd, addr=0x80000000, tag=42
5Device가 DRAM read (64 B cache line)
6Device → Host: S2M DRS MemData, tag=42, payload 64 B
7CPU 데이터 수령, load 완료

Tagoutstanding request 식별 ID. CXL.mem은 out-of-order completion을 허용하므로 여러 read를 동시 issue하고 응답이 임의 순서로 와도 tag로 매칭합니다.

#Write 트랜잭션 흐름

Write는 RwD 채널명령과 데이터를 함께 보냅니다:

단계동작
1CPU 명령: mov [0x80000000], rax
2Host → Device: M2S RwD MemWr, addr=0x80000000, tag=43, 64 B payload
3Device DRAM write
4Device → Host: S2M NDR Cmp, tag=43 (write completion)

Completion이 짧다는 점에 주의 — write data는 RwD에 실어 한 번에 보냄. host는 Cmp 응답만 기다리면 됩니다.

MemWrPtl (Partial Write)은 64 B 미만 쓰기에 사용. write mask를 함께 보내 어느 byte를 update할지 지정.

#HDM Decoder — 주소 매핑의 핵심

CPU가 0x80000000에 load 했을 때, 그 주소가 어느 CXL 디바이스의 어느 DRAM에 해당하는지 결정하는 곳이 HDM Decoder입니다.

항목의미
InputSystem Physical Address (SPA)
OutputDevice Physical Address (DPA) + target device
Configurablehost CPU·CXL switch·CXL device 각 단계에
ProgrammingLinux는 cxl create-region 시 자동

단일 디바이스 매핑:

SPA RangeDevice DPA
0x0000_8000_0000 ~ 0x0000_FFFF_FFFFDevice A: 0x0 ~ 0x7FFF_FFFF (2 GB)

2-way interleave (cache line 단위):

Cache LineSPADeviceDPA
00x80000000A0x0
10x80000040B0x0
20x80000080A0x40
30x800000C0B0x40

(interleave granularity = 64 B)

#Interleave Granularity

Interleave granularity는 64 B(cache line)·256 B·512 B·1 KB·…·16 KB 중 선택.

Granularity장점단점
64 B (cache line)모든 디바이스에 부하 분산DRAM bank parallelism 분산
4 KBDRAM bank parallelism 보존단일 디바이스에 hot spot
16 KBprefetch·sequential read 최적random에 약함

워크로드 access pattern에 따라 선택. Sequential bulk read는 큰 granularity, random random은 64 B.

Linux 확인:

Terminal window
$ cxl list -DT
[
{
"decoder":"decoder3.0",
"resource":0x80000000,
"size":0x80000000,
"interleave_ways":2,
"interleave_granularity":64,
"targets":[
{"target":"mem0", "position":0},
{"target":"mem1", "position":1}
]
}
]

interleave_ways=2, interleave_granularity=64두 디바이스에 cache line 단위 stripe되어 있습니다.

#BISnp — HDM-DB의 Coherency Maintenance

Type 2 디바이스의 HDM-DB 영역은 device cache + host cache같은 line을 공유할 수 있습니다. Device가 자기 cache를 update하면 host cache를 invalidate해야 합니다.

이게 BISnp (Back-Invalidation Snoop). 자세한 흐름은 Ch 3 메모리 일관성에서 다뤘습니다.

#Flit Packing과 Credit Flow Control

CXL.mem 메시지는 *flit (flow control unit)*에 packing되어 PCIe PHY로 전송됩니다.

CXL 세대Flit 크기PHY
1.1·2.0528-bit (66 B)PCIe 5.0
3.0+256 BPCIe 6.0/7.0

자세한 flit 구조는 Ch 9 Flit Format에서.

Credit-based flow controlqueue overflow 방지입니다. host가 N개의 outstanding request slot을 가짐을 device에 알리고, device는 그만큼만 보냅니다. credit이 돌아오면 다시 issue 가능.

이 메커니즘으로 link utilizationqueue depth에 의존합니다. queue 얕으면 stall, 깊으면 latency 폭증적절한 균형튜닝 포인트.

#Linux 측 — Region 생성과 사용

Terminal window
# Decoder 확인
$ cxl list -DT
# Region 생성 (sysfs 또는 cxl-cli)
$ cxl create-region -d decoder0.0 -t ram -s 128G \
-w 2 -g 64 -m mem0,mem1
# -t ram: system RAM 모드
# -w 2: 2-way interleave
# -g 64: 64 B granularity
# -m mem0,mem1: 두 디바이스
# DAX 모드 또는 system RAM 모드 전환
$ daxctl reconfigure-device dax0.0 -m system-ram
# NUMA 노드 확인
$ numactl --hardware
# node 2: CXL.mem region (별도 NUMA)

자세한 Linux drivers/cxl/ 코드 분석Ch 11에서.

#자주 하는 실수

#”CXL.mem이 cache miss마다 CXL 트래픽 발생”

아닙니다. CPU의 L1·L2·L3가 CXL.mem 데이터를 캐시합니다. cache hit이면 CXL 트래픽 0. miss일 때만 CXL 트래픽. cache hit rateCXL.mem 워크로드의 핵심 metric.

#”Type 3 디바이스도 BISnp 필요”

불필요입니다. Type 3는 device 측 cache 없음. coherency는 host CPU의 cache hierarchy전적으로 담당. BISnp 메시지를 host가 처리할 필요도 없음.

#”Interleave granularity는 작을수록 좋다”

워크로드 의존입니다. Sequential access는 4 KB가, random은 64 B가 좋습니다. 잘못 설정하면 대역폭 절반.

#”Tag-based out-of-order completion은 자동”

host CPU의 LSU·메모리 컨트롤러가 reorder를 처리해야 합니다. single-threaded application에서는 의미 적고, multi-threaded·heavy queue에서 효과.

#”CXL.mem load는 DDR load와 동일”

Latency가 다릅니다. DDR5는 80~120 ns, CXL.mem direct는 170~220 ns. 2배 정도 느림. NUMA distance가 다르게 표시되어 Ch 11에서 자세히.

#정리

  • CXL.mem은 host load/store가 64 B cache line 단위 메시지로 변환되는 프로토콜입니다.
  • M2S Req·RwD가 명령, S2M NDR·DRS가 응답. Tag로 out-of-order completion.
  • HDM DecoderSPA → DPA + target device 매핑. interleave 설정 가능.
  • Interleave granularity는 64 B·256 B·…·16 KB 중 선택. 워크로드 access pattern 의존.
  • BISnpHDM-DB Type 2 전용. Type 3는 device cache 없어 BISnp 불필요.
  • Credit-based flow controlqueue depth와 latency의 trade-off를 만듭니다.

#다음 편

Ch 9: Flit Format — 68B vs 256B vs Latency-Optimized에서 CXL의 데이터 단위인 flit 구조세대별로 어떻게 진화했는지를 본격적으로 분해합니다.

#관련 항목

#시리즈 자료 출처 안내

본 글은 CXL Consortium·Linux drivers/cxl/ 소스·hyperscale 측정 자료를 1차 자료로 합니다. CXL 4.0 Specification은 § navigation aid로만 인용. 자세한 spec 인용 정책은 Ch 1 footer 참고.