728x90
- 왜 Phase Tag가 필요한가?
- CQ Tail은 Device가 증가시킨다. Host는 CQ Tail을 모른다.
- Host가 CQ Entry를 consume하고자 할 때, 몇 개의 Entry를 consume해야하는지를 모른다.
- 몇 개의 Entry를 consume해야 하는가를 Entry으 Phase Tag로 알 수 있다.
- CQ Tail값을 Device로부터 읽어오면 안되나요? 된다. 그런데, Mem Read를 해야하므로 성능 측면에서 좋지 않다.
- Device는 CQ Entry의 Phase Tag(bit)를 invert하여 enqueue한다. Host는 consume할 때, entry의 phase tag가 바뀔 때까지 consume하면 된다. n번째 phase tag가 n-1번째와 다르다는 것은 consume해야할 new entry가 아님을 의미한다.
- 예시
- NVMe 환경에서 호스트와 디바이스(컨트롤러) 간의 페이즈 태그 동작을 단계별로 설명하겠습니다.
- 초기 상태
- 호스트는 완료 큐(Completion Queue)를 생성하고 모든 항목의 페이즈 태그를 ‘0’으로 초기화합니다.
- 호스트는 컨트롤러 제어 레지스터(CC.EN)를 ‘1’로 설정하여 NVMe 컨트롤러를 활성화합니다.
- 완료 큐의 헤드 포인터(Head Pointer)와 테일 포인터(Tail Pointer)는 초기값(예: 0)에서 시작합니다.
- 1단계: 첫 번째 완료 항목 추가
- 호스트가 명령 큐(Submission Queue)에 읽기 명령을 추가하고, 컨트롤러에 이를 처리하라고 알립니다(Doorbell 레지스터 업데이트).
- 컨트롤러가 명령을 처리한 후, 완료 큐의 첫 번째 슬롯(인덱스 0)에 완료 항목을 기록합니다.
- 이때 컨트롤러는 페이즈 태그를 ‘1’로 설정합니다(초기값 ‘0’에서 반전).
-
완료 큐 상태: 인덱스 0: 완료 항목 (Phase Tag = 1) 인덱스 1: 빈 항목 (Phase Tag = 0, 초기값) 인덱스 2: 빈 항목 (Phase Tag = 0, 초기값)
- 호스트는 페이즈 태그가 ‘1’인 항목을 보고 새로 추가된 완료 항목임을 인식하고 처리합니다.
- 2단계: 큐가 순환하기 전 추가 완료
- 컨트롤러가 또 다른 명령을 처리하고, 완료 큐의 다음 슬롯(인덱스 1)에 항목을 추가합니다.
- 페이즈 태그는 여전히 ‘1’로 설정됩니다(첫 번째 패스 중이므로).
-
완료 큐 상태: 인덱스 0: 완료 항목 (Phase Tag = 1, 이미 처리됨) 인덱스 1: 완료 항목 (Phase Tag = 1, 새 항목) 인덱스 2: 빈 항목 (Phase Tag = 0)
- 3단계: 큐 순환 후 페이즈 태그 반전
- 완료 큐가 끝까지 채워지고(예: 인덱스 N-1), 컨트롤러가 다시 인덱스 0으로 돌아가 새로운 완료 항목을 기록합니다.
- 이제 두 번째 패스가 시작되었으므로, 컨트롤러는 페이즈 태그를 ‘0’으로 설정합니다(이전 패스의 ‘1’에서 반전).
-
완료 큐 상태: 인덱스 0: 새로운 완료 항목 (Phase Tag = 0) 인덱스 1: 이전 완료 항목 (Phase Tag = 1, 이미 처리됨) 인덱스 2: 이전 완료 항목 (Phase Tag = 1, 이미 처리됨)
- 호스트는 페이즈 태그가 ‘0’인 항목을 보고 새 항목임을 인식합니다.
- 4단계: 호스트의 처리
- 호스트는 완료 큐 헤드 포인터를 이동시키며 페이즈 태그가 반전된 항목을 찾아 처리합니다.
- 완료 큐가 다시 끝까지 채워지면, 다음 패스에서 페이즈 태그는 다시 ‘1’로 반전됩니다.
728x90
반응형
'컴퓨터 > SSD' 카테고리의 다른 글
| [nvme] MSI(Message Signaled Interrupt) (0) | 2025.03.03 |
|---|---|
| [NVMe][OCP] Telemetry (0) | 2024.12.29 |
| [PCIe] Enumeration (0) | 2023.06.22 |
| [NVMe] Reservation (0) | 2023.06.07 |
| [NVMe] Feature (0) | 2023.05.21 |