Part 1: Basics

  • introduction
  • NVMe host-controller interface
  • Queue management

Part 2: Commands

  • NVMe Admin Commands
  • NVM IO Commands
  • NVM SQ Command arbitration
  • Addressing Models: PRP and SGL
  • Get/Set Features commands

Part 3: Architecture

  • Error reporting and handling
  • Firmware updates
  • Controller Registers
  • Controller Initialization
  • Power management
  • Reservations
  • Other NVMe commands
  • Additional changes for v1.3
  • Additional changes for v.14

Appendices

  • PCIe architecture overview

궁금한 점들에 대해선 잊지 않기 위해 메모한다. 

Q: 검정색
A: 빨간색

답변이 작성된 이후 질문은 밑줄 긋는 것을 원칙으로 한다.

 

1.가상 데이터 센터, 클라우드 컴퓨팅...발전의 순서는 어떻게되며 각각은 어떻게 다른 것인가
- 가상화와 클라우드 컴퓨팅은 어떻게 다른 것일까? 같은 것일까? 책에서는 다른 용어로 설명이 된다.
2.스토리지 아케틱처의 진화 과정에 대한 이해 필요
- 서버 중심 스토리지 아키텍처는 무엇인

지, 정보 중심 아키텍처는 무엇인지 등등

Storage가 사용되는 서버 환경은 enterprise 서버와 datacenter 서버 두 가지이다. 

현재 회사 업무로 인해 각 환경에 대한 기본적인 이해가 필요해 공부가 필요한 상황이다.

그러던 중 '정보 스토리지와 관리'를 토대로 세미나 진행한 부서를 발견했고 이 책을 통해 혼자 공부하고자 한다.

Dell EMC에서 만든 책이며, 서버 시스템 아키텍처에 대한 소개 및 컴포넌트들의 기술 소개를 하고 있는 것으로 이해된다. 한글책의 경우 약 600p 정보라 시간을 두고 천천히 읽도록 해야겠다.

4.1 Submission Queue & Completion Queue Definition

해당 장에서 얘기되는 SQ와 CQ는 NVMe over PCIe에서만 적용이 된다. NVMe over Fabrics에 관한 SQ와 CQ의 정보는 NVMe over Fabrics spec을 참조해야 한다.

SQ와 CQ는 circular queue 구조를 가지며, head와 tail을 가지고 있어 entry point를 나타낸다.  

submiiter는 현재 tail entry pointer가 가리키는 queue slot에 command를 저장한 후 tail pointer를 증가시킨다.

consumer는 현재 head entry pointer가 가리키는 slot를 가지고 간 후 head pointer를 증가시킨다.

Queue Empty 상태
• Head == Tail
Queue Full 상태
• Head == Tail + 1 mod # Of Queue Entries.

 

SQ와 CQ의 생성과 삭제는 host software에 의해 요청되어져야 한다.

생성시 CQ가 생성된 이후에 관련된 SQ가 생성된다. 삭제시 SQ가 먼저 메모리 해제된 이후 CQ가 삭제된다.

 

Host software는 새로운 command가 entry로 들어왔다는 것을 통신하기 위해 SQ tail doorbell과 CQ head doorbell에  쓰기를 수행한다. 만약 SQ tail doorbell 또는 CQ head head doorbell에 invalid value 쓰기와 asyn 이벤트 요청 command가 처리되지 않았다면, admin CQ에 invalid doorbell write value status가 놓여지게된다. 문제를 해결 하기 위해 host software에 의해 queue가 삭제 및 재생성되며, controller는 이전에 처리 중이던 command까지만 끝내고 추가적인 command에 대해서 처리하지 않는다. 해당 상황은 host software가 full 상태인 SQ에 entry를 추가하거나 빈 CQ에서 entry를 가지고 갈려는 동작에서 비롯된다.

 

Host software는 새로운 CQ entry가 놓여졌는지 확인하기 위해 CQ entry의 Phage Tag (P) bit를 확인한다. CQ tail pointer는 host에서는 알지 못하고 controller 내부에서만 사용된다. controller는 CQ 항목의 SQHD (SQ Head Pointer) 필드를 사용하여 SQHD의 새 값을 호스트에 전달한다. 

 

Queue identifier: 16 bit ID 값으로 queue가 생성되었을때 할당된다. 이것으로 queue를 식별하게된다.

 

4.2 Submission Queue Entry - Command Format

SQ는 64byte 크기로 구성되어 있다. 하지만, 추후에 spec에 의해서 command format이 변경될수 있다.

(NVMe spec 1.2와 비교해 Dword 0의 15번 bit만 사용되던 것이 spec 1.4에선 [15:14] bit로 확장되었다. 

Dword 0

- [07:00] opcode: 실행하기 위한 command의 opcode를 명시한다.

- [09:08] Fused Operation (FUSE): 간단한 command 두개를 같이 수행하는 command로 만든다. 두개의 command사이에는 어떤 command도 존재하지 않으며, atomic 하게 수행된다.

- [15:14] PRP or SGL for Data Transfer (PSDT): command와 관련된 data를 전송함에 있어 PRPs 또는 SGLs 중 어느 것을 선택할 것인지에 대한 field이다. PRPs는 NVMe over PCIe에서 admin commands를 위해 사용된다. SGLs는 NVMe over Fabrics에서 Admin command 그리고 I/O command를 위해 사용된다. 

- [31:16] Command Identifier (CID): SQ identifier와 함께 조합되어 고유의 identifier를 나타낸다.

 

Dword 1

- [31:00] Namespace Identifier (NSID): command가 적용되는 namespace를 나타낸다. 만약 command에 NSID 값이 사용되지 않는다면 0x0의 값을 가진다. 만약 0xFFFFFFFF의 값을 가진다면 broadcast value(모든 네임 스페이스를 지정하는 데 사용되는 값)이다. 만약 비활성화된(생성은 되었지만 controller에 deattached된 상태) NSID 값을 사용한다면 contoller는 abort 를 status Invalid Field를 남기고 수행한다. invalid NSID 값을 사용한다면 controller는 status Invalid Namespace or Format를 남기고 abort를 수행한다. broadcast value가 지원되지 않는 command 종류에 broadcast value를사용했다면 controller는 status Invalid Field를 남기고 abort를 수행한다.

 

Dword 4, 5

- [63:00] Metadata Pointer (MPTR): MPTR은 logical block data과 interleaved되지 않은 metadata가 command에 있을시에 유효하게 사용된다.

Dword 0의 PSDT field가 0b00인 경우, MPTR field는 metadata의 연속된 physical buffer 주소를 나타낸다. MPTR의 [01:00] 비트가 0b00의 값을 가지지 않는다면, controller는 invalid field 에러를 리포트한다. 

Dword 0의 PSDT field가 0b01인 경우, metadata의 phyiscal buffer 주소를 포함한다. 

Dword 0의 PSDT field가 0b10인 경우, 한개의 SGL descriptor를 포함하는 SGL segment 주소를 포함한다. SGL segment내에 포함된 SGL descriptor는 command를 위한 metadata의 첫번째 SGL descriptor를 나타낸다. 

 

Dword 6~9

- [127:000] Data Pointer (DPTR): command에 포함된 data를 나타낸다. 

Dword 0의 PSDT field가 0b00인 경우, PRP entry 1과 PRP entry2를 나타낸다. 

PRP1: command를 위한 PRP entry 혹은 command와 연관된 PRP list pointer를 나타낸다.

PRP2: 
1) memory page boundary를 초과하는 않는 data 전송의 경우 사용되지 않는다.

2) 전송할 데이터가 하나의 memory page boundary를 초과하는 경우 두번째 memory page의 page base address를 나타낸다. 

3) 전송할 데이터가 하나의 memory page boundary를 초과하고 두개 이상의 memory pages를 가져야 하는 경우 PRP list pointer를 나타낸다. 

Dword 0의 PSDT field가 0b01 또는 0b10인 경우, SGL entry 1(SGL1)으로 사용된다.

Command를 위한 첫번째 SGL segment를 나타낸다. 

4.3 Physical Region Page Entry and List

PRP (Physical region page) entry는 pysical memory page를 가리키는 pointer이다. PRPs는 controller와 memory 사이에 데이터 전송을 위한 scatter/gather mechanism을 사용한다. 효율적인 out of order의 순서로 data를 전송하기 위해 entry는 고정된 사이즈로 사용된다. Pysical memory page는 host software에 의해 CC.MPS에 설정된다. 

위 그림은 PRP entry의 64bit field를 나타낸다. offset은 CC.MPS에 의해 결정된다. 

[64:00] Page Base Address and Offset (PBAO): 4KB의 memory page size라면 [11:00] 12bit(2^12=4KB)가 offset으로 사용된다. 만약 첫번재 PRP entry나 PRP list pointer가 아니라면, offset은 0의 값을 가진다. dword로 align되므로 [01:00] 하위 2bit (2^2=4B)는 0b00의 값으로 된다. 만약 0b00으로 초기화 되지 않으면 PRP Offset Invalid 에러를 controller가 리포트 후 0b00으로 클리어 시킨다. 

PRP List (pysical region page list)는 연속적인 메모리의 single page를 가지는 PRP entry들의 집합이다. 만약 전송해야 할 data가 PRP list pages가 필요하다면 마지막 PRP entry는 다음 PRP list의 pointer를 가리킨다. 만약 non-zero offset을 PRP entry들이 가진다면 PRP offset invalid 에러를 반환한다. 

PRP list는 다음의 수식으로 entry의 개수를 포함하게 된다.

참조:https://lwn.net/Articles/804369/

#define PRP_SIZE			sizeof(__le64)
#define PRP_PER_PAGE		(PAGE_SIZE / PRP_SIZE)

PRP_SIZE는 64bit(8B)이고, PAGE_SIZE는 host page size를 default로 보통 4KB로 고려했을때 하나의 memory page안에 총 512개의 entry가 포함될수 있다. (4096B / 8B = 512개) 또한, 하나의 entry가 physical memory page (4KB)를 가리키므로 2048KB (2MB)의 데이터를 전송할 수 있게된다. 

4.4 Scatter Gather List (SGL)

우선 Scatter Gatehr의 의미를 파악하자.

커널 영역에서 메모리 관리를 할 때는 어렵긴 하지만(오버헤드가 크지만) 물리 메모리에 일렬로 정렬해서 사용하는 것이 가능하지만 사용자 영역에서는 이렇게 할 수가 없다. 커널 영역에서 메모리를 물리 영역에 일렬로 정리해서 쓰는것이 가능하다고 했지만 여기 저기 흩어져 있는(Scatter) 메모리를 일렬로 정렬되어 있는 것처럼 사용할 수 있다면 좀더 편한 관리가 가능할 것이다. 다시 정리하면 Scatter/Gather 의 개념은 여기 저기 흩어져 있는 메모리(Scatter) 를 논리적으로 모아서(Gather) 연속된 물리적 메모리처럼 사용하는 것을 의미하며 Scatterlist 는 여기 저기 흩어져 있는 메모리(Scatter) 의 모음(array) 라고 보면 된다.
출처: https://poplinux.tistory.com/75

struct scatterlist{
  struct page *page;
  unsigned int offset;
  dma_addr_t dma_address;
  unsigned int length;
}

왜 NVMe over PCIe에서는 SGL을 안쓰고 PRP를 쓰는지에 대한 이유이다. 결론은 결국 PRP가 SGL보다 간단하다이다. 하지만, 많은 양의 데이터를 전송할땐 SGL을 사용하는 것이 더 빠르다고 한다.

http://everylwn.blogspot.com/2016/06/sglscatter-gather-list-support-in-nvme_2.html

 

SGL은 데이터 버퍼를 표현하기 위한 memory 주소 공간의 자료구조이다. controller는 'Identify Controller data stucture'에 지원하는 SGL types를 가리킨다. data buffer는 source buffer이거나 destination buffer이다. SGL은 하나 이상의 SGL segment를 포함하고 있다. SGL 내에 Data Block과 Bit Bucket descriptor의 총 길이가 전송할 logical block의 수와 같거나 초과할것이다. 마지막 SGL segment는 SGL segment descriptor 또는 SGL last segment descriptor를 포함하지 않는다. 

SGL segment는 하나 이상의 SGL descriptor를 가진다. 

SGL descriptor의 format이다. 

15B: SGL identifier

[03:00] SGL descriptor sub type: 만약 reserved value이거나 unsupported value인 경우, descriptor는 SGL descriptor type error로 처리된다.

[07:04] SGL descriptor type: 만약 reserved이거나 unsupported value인 경우 SGL descriptor는 SGL descriptor type error로 처리된다. 

SGL data block descriptor인 경우

[07:00] Address:

- SGL descriptor sub type field가 0x0인 경우: address field는 data block의 64bit memory 시작 주소를 나타낸다. 

- SGL descriptor sub type field가 0x1인 경우: 전송되어야 할 memory 주소의 offset을 나타낸다. 

[11:08] Length: data block의 B단위 길이를 나타낸다. 0x0인 경우 전송할 데이터가 존재하지 않는다. 

[15:15] SGL identifier:

- [03:00] SGL descriptor sub type

- [07:04] SGL descriptor type: 0x0

 

SGL bit bucket descriptor인 경우

[11:08] Length: discard되는 source data의 길이를 나타낸다. 만약 destination data buffer인 경우, controller에 의해 discard되는 source data의 길이를 말한다.  만약 source data buffer인 경우 0이다. 

[15:15] SGL identifier:

- [03:00] SGL descriptor sub type

- [07:04] SGL descriptor type: 0x0

4.6 Completion Queue Entry

CQ의 entry는 최소 16B 크기를 가진다. 추후에 I/O coomand set의 사용에 따라 크기가 달라질 수 있다.

Dword 2

[31:16] SQ identifier (SQID): issue된 command와 관련되어 SQ를 구분하기 위한 식별자로 사용된다.

[15:00] SQ Head Pointer (SQHD): command를 가지고온 SQ의 현재 SQ head pointer를 가리킨다. 어디까지 entry가 처리되었는지를 나타낸다.

 

Dword 3

[31:17] Status Field (SF): 처리 완료된 command의 상태를 나타낸다. 

- no fatal or non-fatal error conditions 없이 성공적으로 끝났을 경우 0x0의 값을 가진다. 

- [31] Do Not Retry (DNR): 

--- set to 1: 같은 command가 다시 submmit된 command는 fail된다. 

--- set to 0: 같은 command가 다시 submiit된 command는 성공한다. 

- [30] More (M): 

---set to 1: Get log pag command를 통해 받은 에러 정보보다 더 많은 status 정보를 가지고 있다.

---set to 0: 추가적은 status 정보가 없다.

- [29:28] Command Retry Delay (CRD):

--- set to 0: ?????????????

- [27:25] Status Code Type (SCT): status code type of the completion queue entry

- [24:17] Status Code (SC): status code identifying any error or status information

 

[16:16] Phase Tag (P): CQ entry가 새로운 entry인지 판단하는데 사용된다. CC.EN이 1의 값이 되기전 host software에 의해 0으로 초기화 된다. controller가 CQ에 처리 끝난 entry를 놓은경우, host software가 새로운 entry를 식별할수 있도록 controller는 P field를 invert시킨다.

[15:00] Command Identifier (CID): 처리 완료된 command의 식별자를 가리킨다. 해당 식별자는 host software에 의해 SQ에 command가 놓여질때 할당된다. SQ identifier와 Command identifier의 조합으로 command가 완료되었다는 것을 판단할 수 있다.

4.7 Controller Memory Buffer

CQ

Controller register는 2장 내용중 PCI header 부분에서 나온 MLBAR/MUBAR (PCI BAR0, BAR1) register들을 통해 Host PC의 main memory 영역에 할당되어 있다. Host는 locked access를 할수 없다. 아래의 그림은 SSD controller에서 사용될 register들에 대한 정의이다. 

nvme-cli가 설치되어 있다는 전제하에 실행
#nvme show-regs /dev/nvme0
또는
#nvme show-regs /dev/nvme0 -H

2장에서처럼 마찬가지로 이번에는 controller의 register 값들을 보기 위해 nvme-cli 툴을 사용한다. nvme-cli는 nvme 디바이스에 대해 편리하게 사용하기 위한 commnad line 기반의 management tool이다.

# nvme show-regs --help 결과

nvme show-regs /dev/nvme0만 사용했을 경우엔 hex 값으로 값이 전부 보이며 -H 옵션을 주게 되면 human-readable 옵션으로 보기 좋게 바뀐다. 

# nvme show-regs /dev/nvme0 결과
# nvme show-regs /dev/nvme0 -H 결과

cap     : 200a010fff
	Controller Memory Buffer Supported (CMBS): The Controller Memory Buffer is Not Supported
	Persistent Memory Region Supported (PMRS): The Persistent Memory Region is Not Supported
	Memory Page Size Maximum	   (MPSMAX): 4096 bytes
	Memory Page Size Minimum         (MPSMIN): 4096 bytes
	Boot Partition Support              (BPS): No
	Command Sets Supported              (CSS): NVM command set is supported
	NVM Subsystem Reset Supported     (NSSRS): No
	Doorbell Stride                   (DSTRD): 4 bytes
	Timeout                              (TO): 5000 ms
	Arbitration Mechanism Supported     (AMS): Weighted Round Robin with Urgent Priority Class is not supported
	Contiguous Queues Required	      (CQR): Yes
	Maximum Queue Entries Supported    (MQES): 4096

version : 10200
	NVMe specification 1.2

cc      : 460001
	I/O Completion Queue Entry Size (IOCQES): 16 bytes
	I/O Submission Queue Entry Size (IOSQES): 64 bytes
	Shutdown Notification              (SHN): No notification; no effect
	Arbitration Mechanism Selected     (AMS): Round Robin
	Memory Page Size                   (MPS): 4096 bytes
	I/O Command Sets Selected          (CSS): NVM Command Set
	Enable                              (EN): Yes

csts    : 1
	Processing Paused               (PP): No
	NVM Subsystem Reset Occurred (NSSRO): No
	Shutdown Status               (SHST): Normal operation (no shutdown has been requested)
	Controller Fatal Status        (CFS): False
	Ready                          (RDY): Yes

nssr    : 0
	NVM Subsystem Reset Control (NSSRC): 0

intms   : 0
	Interrupt Vector Mask Set (IVMS): 0

intmc   : 0
	Interrupt Vector Mask Clear (IVMC): 0

aqa     : 1f001f
	Admin Completion Queue Size (ACQS): 32
	Admin Submission Queue Size (ASQS): 32

asq     : 303d9000
	Admin Submission Queue Base (ASQB): 303d9000

acq     : 34580000
	Admin Completion Queue Base (ACQB): 34580000

cmbloc  : 3
	Offset                                                        (OFST): 0x0 (See cmbsz.szu for granularity)
	CMB Queue Dword Alignment                                     (CQDA): 0
	CMB Data Metadata Mixed Memory Support                      (CDMMMS): Enforced
	CMB Data Pointer and Command Independent Locations Support (CDPCILS): Enforced
	CMB Data Pointer Mixed Locations Support                    (CDPMLS): Enforced
	CMB Queue Physically Discontiguous Support                   (CQPDS): Enforced
	CMB Queue Mixed Memory Support                               (CQMMS): Enforced
	Base Indicator Register                                        (BIR): 0x3

cmbsz   : 500003
	Size                      (SZ): 1280
	Size Units               (SZU): 4 KB
	Write Data Support       (WDS): Write Data and metadata transfer in Controller Memory Buffer is Not supported
	Read Data Support        (RDS): Read Data and metadata transfer in Controller Memory Buffer is Not supported
	PRP SGL List Support   (LISTS): PRP/SG Lists in Controller Memory Buffer is Not supported
	Completion Queue Support (CQS): Admin and I/O Completion Queues in Controller Memory Buffer is Supported
	Submission Queue Support (SQS): Admin and I/O Submission Queues in Controller Memory Buffer is Supported

bpinfo  : ffffffff
	Active Boot Partition ID      (ABPID): 1
	Boot Read Status                (BRS): Error completing Boot Partition read
	Boot Partition Size            (BPSZ): 32767
bprsel  : ffffffff
	Boot Partition Identifier      (BPID): 1
	Boot Partition Read Offset    (BPROF): fffff
	Boot Partition Read Size      (BPRSZ): 3ff
bpmbl   : ffffffffffffffff
	Boot Partition Memory Buffer Base Address (BMBBA): ffffffffffffffff
cmbmsc	: ffffffffffffffff
	Controller Base Address (CBA)	     : fffffffffffff
	Controller Memory Space Enable (CMSE): 1
	Capabilities Registers Enabled (CRE) : CMBLOC and CMBSZ registers are enabled

cmbsts	: ffffffff
	Controller Base Address Invalid (CBAI): 1

pmrcap  : ffffffff
	Controller Memory Space Supported (CMSS)		   : Referencing PMR with host supplied addresses is Supported
	Persistent Memory Region Timeout		    (PMRTO): ff
	Persistent Memory Region Write Barrier Mechanisms(PMRWBM): f
	Persistent Memory Region Time Units		    (PMRTU): PMR time unit is minutes
	Base Indicator Register			      (BIR): 7
	Write Data Support				      (WDS): Write data to the PMR is supported
	Read Data Support				      (RDS): Read data from the PMR is supported
pmrctl  : ffffffff
	Enable (EN): PMR is READY
pmrsts  : ffffffff
	Controller Base Address Invalid (CBAI): 1
	Health Status			  (HSTS): Reserved
	Not Ready			  (NRDY): The Persistent Memory Region is Not Ready to process PCI Express memory read and write requests
	Error				  (ERR) : ff
pmrebs  : ffffffff
	PMR Elasticity Buffer Size Base  (PMRWBZ): ffffff
	Read Bypass Behavior			   : memory reads not conflicting with memory writes in the PMR Elasticity Buffer SHALL bypass those memory writes
	PMR Elasticity Buffer Size Units (PMRSZU): Reserved
pmrswtp : ffffffff
	PMR Sustained Write Throughput       (PMRSWTV): ffffff
	PMR Sustained Write Throughput Units (PMRSWTU): Reserved/second
pmrmsc	: ffffffffffffffff
	Controller Base Address (CBA)		: fffffffffffff
	Controller Memory Space Enable (CMSE	: 0

 위 결과는 -H 옵션을 주고 실행했을때의 결과이다. 

  • CAP -controller capabilities
    • 8B의 크기를 가지고 있다.
    • 값: 0x200a010fff
    • controller의 특성을 host software에게 알려준다. 
    • nvme-cli에서는 admin passthru command를 통해 register 값을 읽어 온다.
    • Controller Memory Buffer Supported (CMBS): The Controller Memory Buffer is Not Supported 
    • Persistent Memory Region Supported (PMRS): The Persistent Memory Region is Not Supported 
    • Memory Page Size Maximum    (MPSMAX): 4096 bytes
    • Memory Page Size Minimum         (MPSMIN): 4096 bytes
    • Boot Partition Support              (BPS): No
    • Command Sets Supported              (CSS): NVM command set is supported
    • NVM Subsystem Reset Supported     (NSSRS): No
    • Doorbell Stride                   (DSTRD): 4 bytes
    • Timeout                              (TO): 5000 ms
    • Arbitration Mechanism Supported     (AMS): Weighted Round Robin with Urgent Priority Class is not supported
    • Contiguous Queues Required       (CQR): Yes
    • Maximum Queue Entries Supported    (MQES): 4096 

nvme-cli show-regs의 마지막 전달 과정

  • VS - version에 대한 것을 나타냄. 1.0 ~ 1.4까지 존재함. 
    • 4B를 가진다.
    • 값: 0x10200
    • NVMe specification 1.2

  • intms - interrupt mask set  
    • 4B를 가진다.
    • 값: 0 Interrupt Vector Mask Set (IVMS): 0 

  • intmc - interrupt mask clear
    • 4B를 가진다.
    • 값: 0 Interrupt Vector Mask Clear (IVMC): 0

  • CC - controller configuration
    • 해당 register는 controller를 위한 셋팅을 변경한다.
    • Host가 가능한 부분
      • Arbitraction mechanism (CC.AMS)
      • Memory page size (CC.MPS)
      • Command set (CC.CSS)
    • cc      : 460001
    • I/O Completion Queue Entry Size (IOCQES): 16 bytes
    • I/O Submission Queue Entry Size (IOSQES): 64 bytes
    • Shutdown Notification              (SHN): No notification; no effect
    • Arbitration Mechanism Selected     (AMS): Round Robin
    • Memory Page Size                   (MPS): 4096 bytes
    • I/O Command Sets Selected          (CSS): NVM Command Set
      • controller가 diable되었을대 (CC.EN == 0) 설정을 변경할 수 있다.
    • Enable                              (EN): Yes 

  • NSSR - NVM subsystem reset
    • NVM Subsystem Reset Control (NSSRC): 0
    • CAP.NSSRS와 관련

  • AQA - admin queue attributes
    • 값: 1f001f 
    • Admin Completion Queue Size (ACQS): 32
    • Admin Submission Queue Size (ASQS): 32 

  • asq     : 303d9000
    • Admin Submission Queue Base (ASQB): 303d9000
  • acq     : 34580000
    • Admin Completion Queue Base (ACQB): 34580000

cmbloc  : 3
Offset                                                        (OFST): 0x0
CMB Queue Dword Alignment                                     (CQDA): 0
CMB Data Metadata Mixed Memory Support                      (CDMMMS): Enforced
CMB Data Pointer and Command Independent Locations Support (CDPCILS): Enforced
CMB Data Pointer Mixed Locations Support                    (CDPMLS): Enforced
CMB Queue Physically Discontiguous Support                   (CQPDS): Enforced
CMB Queue Mixed Memory Support                               (CQMMS): Enforced
Base Indicator Register                                        (BIR): 0x3

cmbsz   : 500003
Size                      (SZ): 1280
Size Units               (SZU): 4 KB
Write Data Support       (WDS): Write Data and metadata transfer in Controller Memory Buffer is Not supported
Read Data Support        (RDS): Read Data and metadata transfer in Controller Memory Buffer is Not supported
PRP SGL List Support   (LISTS): PRP/SG Lists in Controller Memory Buffer is Not supported
Completion Queue Support (CQS): Admin and I/O Completion Queues in Controller Memory Buffer is Supported
Submission Queue Support (SQS): Admin and I/O Submission Queues in Controller Memory Buffer is Supported

bpinfo  : ffffffff
Active Boot Partition ID      (ABPID): 1
Boot Read Status                (BRS): Error completing Boot Partition read
Boot Partition Size            (BPSZ): 32767

bprsel  : ffffffff
Boot Partition Identifier      (BPID): 1
Boot Partition Read Offset    (BPROF): fffff
Boot Partition Read Size      (BPRSZ): 3ff

bpmbl   : ffffffffffffffff
Boot Partition Memory Buffer Base Address (BMBBA): ffffffffffffffff

cmbmsc : ffffffffffffffff
Controller Base Address (CBA)      : fffffffffffff
Controller Memory Space Enable (CMSE): 1
Capabilities Registers Enabled (CRE) : CMBLOC and CMBSZ registers are enabled

cmbsts : ffffffff
Controller Base Address Invalid (CBAI): 1

pmrcap  : ffffffff
Controller Memory Space Supported (CMSS)    : Referencing PMR with host supplied addresses is Supported
Persistent Memory Region Timeout     (PMRTO): ff
Persistent Memory Region Write Barrier Mechanisms(PMRWBM): f
Persistent Memory Region Time Units     (PMRTU): PMR time unit is minutes
Base Indicator Register       (BIR): 7
Write Data Support       (WDS): Write data to the PMR is supported
Read Data Support       (RDS): Read data from the PMR is supported

pmrctl  : ffffffff
Enable (EN): PMR is READY

pmrsts  : ffffffff
Controller Base Address Invalid (CBAI): 1
Health Status   (HSTS): Reserved
Not Ready   (NRDY): The Persistent Memory Region is Not Ready to process PCI Express memory read and write requests

pmrebs  : ffffffff
PMR Elasticity Buffer Size Base  (PMRWBZ): ffffff
Read Bypass Behavior    : memory reads not conflicting with memory writes in the PMR Elasticity Buffer SHALL bypass those memory writes
PMR Elasticity Buffer Size Units (PMRSZU): Reserved

pmrswtp : ffffffff
PMR Sustained Write Throughput       (PMRSWTV): ffffff
PMR Sustained Write Throughput Units (PMRSWTU): Reserved/second

pmrmsc : ffffffffffffffff
Controller Base Address (CBA) : fffffffffffff
Controller Memory Space Enable (CMSE : 0

NVMe Spec 2장에서는 어떻게 PCI header, PCI capabilities, PCIe extended capabilites가 NVMe controller에 대해 구성되어 있는지를 살펴 본다.

PCIe registers

PCIe register에 대한 큰 틀에서의 구성이다. SSD 내에 존재하는 controller의 PCIe와 관련된 IP의 register들에 대한 설정이다. PCI header는 0x00 ~ 0x3F까지 범위이며, 뒤의 register들은 펌웨어에서 메모리 어느 부분에 베이스 주소를 가지고 갈 것인지에 따라 다르게 설정될수 있다.

가장 먼저 PCI header에 대해 살펴 볼 것이다.

PCI Header

PCI header는 디바이스의 타입에 따라 Type 0, Type 1 두 종류로 나뉘며 Type에 따라 header의 bit가 다르게 사용된다. 하지만, 여기에서는 RC 혹은 Bridge를 사용한 디바이스가 아닌 RC에 다이렉트로 연결된 End device를 가정으로 설명한다. 

  • Type 0 header: PCI Express 디바이스
  • Type 1 header: Switch 및 Root Complex 가상 PCI Bridges

Type 0 header
PCI header 설명

그리고 PCI header에 대해 spec을 그냥 읽는 것 보다는 하나의 디바이스를 예제로 보는 것이 좋기 때문에 아래처럼 실행하자. 

$ lspci -x

 

$ lspci --help 결과

PCI slot에 연결된 디바이스들에 대해 정보를 알기 위해선 리눅스에서 lspci 명령을 통해 알수 있다. Configuration address 중 PCI header 부분에 대해서만 알고 싶다면 -x 옵션을 전체 4KB에 대한 영역 전부 알고 싶다면 -xxx 옵션을 주면 된다. 아래는 Virutual box에서 가상으로 생성한 NVMe device의 결과이다. 

$ lspci -x 결과

  • ID - identifiers
    • ID 값에 대한 비트 필드를 나타낸다. 
    • vendor ID와 devie ID 두개의 필드를 가진다.
    • vendor ID: 80ee
    • devcie ID: 4e56
    • 삼성 디바이스의 경우 144d의 vendor ID를 가지게 된다. 
    • vendor ID list를 보고 싶으면 여기를 들어가면 볼 수 있다.

  • CMD - command
    • 2B의 값을 가진다. 
    • 값: 0x0007
    • Enable 
      • I/O space enable
      • Memory space enable
      • bus master enable
    • device로 하여금 I/O space와 memory space 영역에 접근을 가능하도록 한다. 
    • bus master로 동작하기 때문에 위의 영역을 통해 데이터 전송을 할 수 있다. (어떤 데이터를 주고 받는 것일까?)

  • STS - device status
    • 2B의 값을 가진다.
    • 값: 0x0010
    • Enable
      • capabilites list
    • capabilities list가 존재 함을 나타낸다. 

  • RID - revision ID
    • 1B의 값을 가진다.
    • 값: 0x00
    • controller의 수정 버전을 나타내는 것 같다. (확실치 않음, 내가 본 5대의 SSD는 모두 0의 값을 가짐)

  • CC - class code
    • 3B의 값을 가진다.
    • 값: 0X010802
    • Programming interface : 0x02, 즉 I/O controller가 있음을 나타낸다.
    • sub class code : 0x08
    • base class code: 0x01
    • PCI의 class 분류를 볼려면 여기를 누르면 된다.
    • 대 분류, 중분류라고 생각 하면 될거 같다. mass storage 중에서도 플로피 디스크, IDE 등 다양한 storage들이 존재하는데 그 중에서 sub class code가 0x08이므로 non-volatile memory를 나타낸다. 

  • CLS - cache line size
    • 1B의 값을 가진다. 
    • 현재 여기에서는 0의 값을 가져 cache 가 없는 것으로 확인 되지만, 실제 SSD중 일부 제품의 경우 해당 크기가 정해져있는 것으로 확인 되었다. 

  • MLT - master latency timer
    • 1B의 값을 가진다. 
    • 값: 0X40

  • HTYPE - header type
    • 1B의 값을 가진다. 
    • 여기에서는 두개의 필드 모두 0의 값을 가진다. 하지만, NVM subsyetem에서 multi function을 지원하는 경우 해당 7번 bit는 set된다.

  • BIST - build in self test
    • 1B의 값을 가진다.
    • 모두 0의 값을 가진다. BIST를 지원하지 않는다. 

  • MLBAR - memory register base address
    • 4B의 값을 가진다.
    • 값: 0xf0808000

  • MUBAR - memory register base address
    • MLBAR의 base address와 합쳐서 최대 64bit의 base address 주소 공간을 가질 수 있다. 

  • BAR2 - index/data pair register base address
    • 4B의 값을 가진다.
    • 값: 0x0000d271

  • CCPTR - cardbus cis pointer
    • 지원 안함

+ Recent posts