본문 바로가기
Computer Architecture

PCIe Configuration Space

by hyeyoo 2023. 11. 30.
※ 이 블로그의 글은 글쓴이가 공부하면서 정리하여 쓴 글입니다.
※ 최대한 내용을 검토하면서 글을 쓰지만 틀린 내용이 있을 수 있습니다.
※ 만약 틀린 부분이 있다면 댓글로 알려주세요.

Bus, Device, Function

Configuration Space와 Enumeration을 다루기 전에, BDF (Bus, Device, Function)이 무엇인지 알아보자. PCI와 PCIe에서는 PCI 도메인(or PCI 세그먼트)당 최대 256개의 버스가 존재할 수 있고, 버스당 최대 32개의 디바이스, 디바이스당 최대 8개의 펑션(function)이 존재할 수 있다. PCI(e) 시스템에서 (Bus, Device, Function)은 PCI 도메인 (or PCI 세그먼트) 내에서 디바이스를 식별할 수 있다. 리눅스에서는 'lspci' 명령어로 PCI(e) 디바이스의 B/D/F를 확인할 수 있다.

PCI(e) Configuration Space

운영체제는 어떻게 디바이스와 상호작용할까?

프로세서는 모든 작업을 명령어의 실행으로 처리한다. 아무 명령어나 실행할 수 있는 것은 아니고, 명령어 집합 (i.e. Intel x86-64 ISA, ARM A64 ISA)에서 지원하는 명령어만 실행할 수 있다.  어떤 명령어는 메모리로부터/메모리에 데이터를 읽고 쓰고, 어떤 명령어는 산술 연산과 논리 연산을 수행한다.

프로세서가 디바이스에 데이터를 전달하거나 명령어을 전달하는 것도 동일하게 명령어의 실행으로 수행된다. 만약 메인 메모리 접근과 I/O 연산에 같은 명령어를 사용한다면 Memory-Mapped IO라고 하고, I/O 연산을 위한 별도의 명령어를 사용한다면 Port-Mapped IO라고 한다. [1] x86 아키텍처는 MMIO와 PMIO 모두 지원하지만, PMIO에서 사용하는 I/O 주소 공간의 크기가 64KiB (0x0000 ~ 0xFFFF)밖에 되지 않는다.

PCI(e)에는 크게 세 가지 주소 공간이 있다.

  1. Memory Address Space
  2. I/O Address Space
  3. Configuration Space

1번과 2번은 디바이스의 레지스터 혹은 메모리에 접근하는 데 사용된다. (단, PCIe에서 legacy endpoint가 아닌 PCIe endpoint는 I/O Address Space는 사용하지 않는다.) 1번, 2번과 달리 3번 Configuration Space는 PCI(e)에서 디바이스를 발견하고, 주소 공간을 할당하고, 디바이스에서 어떤 PCI(e) 기능 (capability)을 지원하는지 알아내는 등의 용도로 쓰인다. 디바이스 레지스터가 어떤 시맨틱으로 동작하느냐는 디바이스마다 다르지만, PCI(e) 디바이스는 모두 Configuration Space를 지원해야 하므로 디바이스 종류에 관계 없이 같은 방법으로 디바이스를 발견하고 설정할 수 있다. Configuration Space는 Function마다 하나씩 존재한다. 디바이스가 4개의 Function을 지원한다면, Configuration Space도 4개다.

Accessing Configuration Space

Configuration Space에 접근하는 법은 크게 두 가지가 있다. 각각 하나씩 살펴보자. Configuration Space의 크기는 PCI에서 256B이고 PCIe에서 4KiB다. PCIe의 Configuration Space는 PCI와의 소프트웨어 하위호환성을 위해 첫 256B는 PCI의 Configuration Space를 동일하게 구현한다.

이 섹션에서는 Configuration Space를 접근하는 레거시 방법과 ECAM을 다룬다. PCI, PCIe 모두 레거시 방법으로 첫 256바이트에 해당하는 Configuration Space에 접근할 수 있다. PCI를 위해서 작성된 소프트웨어는 ECAM을 모르기 때문에, 하지만 PCIe는 PCI에 대한 소프트웨어 하위호환성을 제공하기 때문에 PCIe에서도 레거시 방법으로 Configuration Space에 접근할 수 있다. 하지만 PCIe Configuration Space의 나머지 3840B는 레거시 방법으로는 접근할 수 없으며 ECAM으로만 접근할 수 있다.

The legacy method

첫 번째 방법에는 Configuration Space의 접근에 I/O Address Space 상의 두 개의 (32-bit x 2)가 사용된다. 하나는 CONFIG_ADDRESS 라고 불리는 0xCF8에 위치한 DWORD고, 나머지 하나는 CONFIG_DATA라고 불리는 0xCFC에 위치한 DWORD다. CONFIG_DATA는 Configuration Space 레지스터에 데이터를 읽거나 쓸 때 사용하는 주소고,  CONFIG_ADDRESS는 CONFIG_DATA에 데이터를 읽고 쓸 때, "어떤 디바이스의 Configuration Space이고, 해당 Configuration Space에서 어느 Offset에 접근할지"를 정한다. CONFIG_ADDRESS의 레이아웃은 다음과 같다.

CONFIG_ADDRESS: I/O Address Space의 0xCF8 (출처: https://wiki.osdev.org/PCI)

Enable Bit (bit 32)은 CONFIG_DATA에 대한 접근을 Configuration Space에 대한 접근으로 변환할지를 결정한다. 만약 Enable Bit이 1이라면, Bit 23-16, 15-11, 10-8은 디바이스의 BDF를 결정한다. 마지막으로 Bit 7-0은 Register Offset으로, 해당 BDF의 Configuration Space의 몇 번째 바이트에 접근할지를 결정한다. (단, 레지스터는 DWORD 단위로 접근하므로 비트 0-1은 항상 0이다.) [2] 이 방법은 PCI에서 사용하던 방법이며 PCI는 256바이트 크기의 Configuration Space를 사용했다. 

ECAM (Enhanced Configuration Access Mechanism)

두 번째 방법이 PCIe에서 도입된 ECAM (Enhanced Configuration Access Mechanism)이다. ECAM은 시스템의 물리 주소 공간 중, 일부를 사용하여 MMIO 방식으로 Configuration Space에 접근하는 용도로 쓰는 것이다. 물리 주소 공간 중 일부가 사용되기 때문에, Configuration Space의 크기만큼 사용 가능한 물리 주소 공간이 줄어든다. 물론 64비트 프로세서는 보통 36 ~ 52 비트를 물리 주소 공간을 표현하는 데에 사용하기 때문에 큰 문제는 아니다.

PCIe에서는 Configuration Space의 크기가 4KiB이므로, PCI 도메인 (혹은 PCI 세그먼트)당 (256개의 Bus) * (32개의 Device) * (4개의 Function) * (4KiB) = 256MiB의 물리 주소 공간이 필요하다. Configuration Space의 위치는 펌웨어가 ACPI MCFG 테이블을 통해서 운영체제에 알려주어야 한다.

Configuration Space는 ACPI MCFG 테이블에 명시된 시작 주소에서, BDF (0, 0, 0)부터 (255, 31, 7)까지의 Configuration Space가 순차적으로 하나씩 존재한다. 다음 그림은 Configuration Space의 시작 주소와 BDF 번호로 특정 Function의 Configuration Space 시작 주소를 계산하는 방법을 설명한다.

PCIe Configuration Space Layout

앞서 설명했듯 PCIe의 Configuration Space는 4KiB이며, 4KiB 중 PCI Configuration Space에 해당하는 256B는 PCI에서 사용하던 레지스터들을 동일하게 구현한다.

PCI Configuration Space의 256바이트 중 처음 64바이트는 "표준 레지스터"들로, 동작이 PCI 스펙 상으로 정의되어 있다. 256 바이트 중 64 바이트를 제외한 나머지 192 바이트는 표준에서 용도를 정의하기 때문에, 벤더마다 다르게 동작할 수 있다. 하지만 192바이트 중 일부를 "Capability List"로 사용하는 경우, 디바이스가 PCI capability들을 지원하는지  운영체제와 펌웨어에 전달하는 목적으로 사용될 수 있다. [1] 예를 들어서 PCI 디바이스가 MSI/MSI-X 인터럽트를 지원하려면 Capability ID가 0x5 (MSI) or 0x11 (MSI-X)인 Capability Register를 192바이트 중 일부에 위치시켜야 한다. Capabiliy List의 시작 위치는 Capability Pointer (0x34)를 읽으면 알 수 있다.

PCI Standard Registers (First 64 Bytes) (https://en.wikipedia.org/wiki/PCI_configuration_space 의 수정본)

PCIe의 Configuration Space 4KiB 중 256B를 제외한 3840B는 PCI의 Capability List와 유사하게 Extended Capability의 List로 구성된다. 오프셋 0x100 (256)부터 Extended Capability List가 시작된다. [1]

참고 문서

[1] https://en.wikipedia.org/wiki/PCI_configuration_space

 

PCI configuration space - Wikipedia

From Wikipedia, the free encyclopedia Auto-configuration mechanism used by PCI PCI configuration space is the underlying way that the Conventional PCI, PCI-X and PCI Express perform auto configuration of the cards inserted into their bus. Overview[edit] PC

en.wikipedia.org

[2] https://wiki.osdev.org/PCI

 

PCI - OSDev Wiki

The PCI Bus The PCI (Peripheral Component Interconnect) bus was defined to establish a high performance and low cost local bus that would remain through several generations of products. By combining a transparent upgrade path from 132 MB/s (32-bit at 33 MH

wiki.osdev.org

[3] https://wiki.osdev.org/PCI_Express#Enhanced_Configuration_Mechanism

 

PCI Express - OSDev Wiki

This page or section is a work in progress and may thus be incomplete. Its content may be changed in the near future. The PCI Express bus is a backwards compatible, high performance, general purpose I/O interconnect bus, and was designed for a range of com

wiki.osdev.org

'Computer Architecture' 카테고리의 다른 글

PCIe Enumeration  (0) 2023.11.30
An Introduction to PCI Express  (0) 2023.11.15
PIPT / VIVT / VIPT 캐시와 flush_dcache_folio()  (0) 2022.06.25
다시 정리하는 NUMA  (0) 2022.01.21
LEGv8 ISA - 특징과 명령어 포맷  (0) 2021.12.02

댓글