BAR trong PCIe là gì?

Giải thích BAR trong PCIe: Base Address Register, MMIO/I/O BAR, 32-bit/64-bit BAR, prefetchable, sizing, resource allocation và debug MMIO fail.

Cập nhật 15 phút đọc
PCI cover

Bạn thấy PCI device ở 02:00.0, Vendor ID đúng, Class Code đúng. Driver gọi PciIo->GetBarAttributes() cũng thấy BAR0 có base address. Nhưng khi đọc register trong BAR thì toàn 0xFFFFFFFF, hoặc access fault. Có khi BAR bằng 0, có khi 64-bit BAR bị driver parse nhầm thành hai BAR độc lập. Đây là nhóm bug rất phổ biến khi làm PCIe firmware.

Điểm cần hiểu là BAR.

Nói ngắn gọn: BAR, Base Address Register, là register trong PCI Configuration Space dùng để khai báo và chứa base address của vùng tài nguyên mà device cần, thường là MMIO hoặc I/O port. Firmware/OS probe BAR size, cấp address range, cấu hình bridge window và bật Command Register để driver có thể access device registers.

BAR nằm ở đâu?

BAR trong PCI Configuration Space

PCI Function Configuration Space
├─ 0x00: Vendor ID / Device ID
├─ 0x04: Command / Status
├─ 0x08: Revision / Class Code
├─ 0x0E: Header Type
├─ 0x10: BAR0
├─ 0x14: BAR1
├─ 0x18: BAR2
├─ 0x1C: BAR3
├─ 0x20: BAR4
├─ 0x24: BAR5
└─ Capability List...

Endpoint Header Type 0 có tối đa 6 BAR. Bridge Header Type 1 có layout khác, nên không được parse như endpoint thường.

BAR trong enumeration flow

01 Read

Read BAR original value

Firmware lưu BAR hiện tại trước khi sizing.

02 Probe

Write all 1s

Ghi 0xFFFFFFFF để device phản hồi size mask.

03 Size

Read size mask

Tính size và type của BAR.

04 Alloc

Allocate resource

Cấp MMIO/I/O range phù hợp từ root bridge aperture.

05 Write

Program BAR base

Ghi base address vào BAR.

06 Window

Program bridge windows

Bridge phía trên phải forward range đó.

07 Enable

Set Command Register

Bật Memory Space, I/O Space hoặc Bus Master khi cần.

Firmware probe BAR size, allocate resource, ghi base address và enable decode.

Các loại BAR

Các loại BAR thường gặp
Loại BAR Ý nghĩa Debug khi lỗi
Memory BAR MMIO register/resource Driver map MMIO để access registers
I/O BAR I/O port resource Cần I/O Space Enable
32-bit Memory BAR Base address trong 32-bit address space Below 4G resource
64-bit Memory BAR BAR dùng hai register liên tiếp Parser sai làm mất BAR kế tiếp
Prefetchable BAR Memory có thể prefetch/cache policy đặc biệt Cần prefetchable bridge window
Non-prefetchable BAR MMIO register thông thường Không map như prefetchable bừa
Resizable BAR BAR size có thể thay đổi qua capability Resource allocation thay đổi theo policy
Unimplemented BAR BAR không dùng Read/probe ra 0 hoặc size 0

BAR bit layout cơ bản

BAR raw value có vài bit thấp dùng để mô tả type, không phải base address.

BAR raw value concept
Bit/field Memory BAR I/O BAR
Bit 0 0 nghĩa là Memory BAR 1 nghĩa là I/O BAR
Bits 2:1 Memory type, ví dụ 32-bit hoặc 64-bit Reserved/khác theo I/O
Bit 3 Prefetchable bit Không dùng như memory prefetchable
Base address bits Upper bits sau khi mask low bits I/O base sau khi mask low bits
Alignment Theo size BAR Base phải aligned
64-bit Dùng BARn và BARn+1 Không áp dụng kiểu memory 32-bit
Sizing mask Read sau write all 1s Dùng tính size
Assigned base Firmware/OS ghi base vào BAR Driver dùng base để map access

64-bit BAR

64-bit BAR chiếm hai BAR register liên tiếp. Nếu BAR0 là 64-bit, thì BAR1 là phần high của cùng BAR, không phải resource độc lập.

64-bit BAR example

BAR0 low dword
├─ Bit 0 = 0: Memory BAR
├─ Bits 2:1 = 10b: 64-bit memory BAR
├─ Bit 3 = Prefetchable flag
└─ Base address low bits

BAR1 high dword
└─ Base address high bits

Next usable BAR
└─ BAR2, not BAR1
64-bit BAR debug
Vấn đề Biểu hiện Cách kiểm tra
Parser coi BAR1 là BAR riêng Resource list sai Nếu BAR0 64-bit, skip BAR1
High dword không ghi đúng Base address sai trên above 4G Read back BAR0/BAR1
Above 4G disabled Không cấp được large/64-bit BAR Check setup/resource policy
Bridge window 32-bit Endpoint BAR above 4G không forward Check prefetchable 64-bit window
Driver truncate address MMIO access sai Use UINT64/EFI_PHYSICAL_ADDRESS
BAR size lớn Resource allocation fail Check root bridge aperture
Resizable BAR Size không như expected Check capability/policy
Alignment Base phải aligned theo BAR size Misaligned assignment invalid

BAR sizing hoạt động thế nào?

Firmware/OS thường dùng quy trình probe size: ghi all 1s vào BAR, đọc lại mask, tính size, rồi restore/program base.

1. Save original BAR
2. Write 0xFFFFFFFF to BAR
3. Read back size mask
4. Mask type bits
5. Calculate size
6. Restore/program assigned base
BAR sizing checklist
Bước Cần đúng Bug nếu sai
Save original Lưu BAR trước khi probe Mất base cũ
Disable decode nếu cần Tránh decode trong lúc sizing Transaction conflict
Write all 1s Đúng width 32/64-bit Size mask sai
Read mask Mask type bits Size tính sai
64-bit handling Probe low/high đúng Truncate size/base
Restore/program Ghi base address hợp lệ BAR = 0 hoặc wrong base
Alignment Base aligned theo size Device không decode đúng
Bridge/root resource Có window chứa resource MMIO fail dù BAR set

Prefetchable BAR

Prefetchable BAR cho biết vùng memory có thể được CPU/bridge prefetch theo rule nhất định. Nhưng không phải mọi MMIO register đều prefetchable.

Prefetchable vs Non-prefetchable BAR
Khía cạnh Prefetchable BAR Non-prefetchable BAR
Ý nghĩa Memory có thể prefetch nếu semantics cho phép MMIO register cần strict ordering
Bridge window Prefetchable memory window Memory window thường
Cache policy Có thể khác tùy OS/platform Thường UC/device mapping
Thiết bị Framebuffer/large memory window có thể prefetchable Control registers thường non-prefetchable
Bug nếu sai Ordering/data coherency issue Performance thấp hoặc access issue
64-bit window Thường liên quan large BAR Có thể below 4G
Debug Check BAR bit 3 Check bridge prefetch window
Security Không map user-accessible bừa Không map RWX hoặc cache sai

BAR và Bridge Window

BAR của endpoint phía sau bridge phải nằm trong bridge window của tất cả bridges phía trên.

01 CPU

CPU accesses MMIO address

Driver đọc/ghi register trong BAR.

02 Root

Root complex routes transaction

Address thuộc PCIe MMIO aperture.

03 Bridge

Bridge window forwards

Bridge kiểm tra address nằm trong memory/prefetch window.

04 Endpoint

Endpoint BAR decodes

Device nhận transaction nếu BAR range match.

05 Reg

Register access

Device trả data hoặc thực hiện write.

Endpoint BAR access đi qua bridge windows.
BAR và bridge window
Điều kiện Cần đúng Nếu sai
Endpoint BAR base Assigned address hợp lệ BAR = 0 hoặc wrong base
BAR size Size đủ và aligned Overlap hoặc access ngoài range
Bridge memory window Chứa non-prefetchable BAR Transaction không forward
Bridge prefetch window Chứa prefetchable BAR Large/prefetch BAR fail
Root bridge aperture Chứa toàn bộ resource Allocator không cấp được
Command Memory Enable Endpoint decode bật Device không respond
Bridge command Bridge forwarding bật Downstream fail
Page table/cache OS/firmware map đúng CPU fault hoặc cache bug

BAR và Command Register

BAR assign xong vẫn cần Command Register enable tương ứng.

Command Register liên quan BAR
Bit Liên quan BAR nào Lỗi nếu chưa bật
Memory Space Enable Memory/MMIO BAR MMIO access không response
I/O Space Enable I/O BAR I/O port access không response
Bus Master Enable DMA từ device Device không DMA được
Interrupt Disable INTx legacy Interrupt behavior khác
SERR Enable Error reporting Error không propagate
Parity Error Response Error handling Debug bus error khó
Read-modify-write Không phải bit, nhưng là cách ghi đúng Ghi hardcode clear nhầm bit
Bridge command Bridge cũng có command Downstream forwarding issue

BAR và EFI_PCI_IO_PROTOCOL

UEFI PCI driver thường không tự lấy BAR raw rồi map trực tiếp. Nó dùng EFI_PCI_IO_PROTOCOL để đọc BAR attributes, map MMIO và enable attributes.

EFI_PCI_IO_PROTOCOL và BAR
API/nhóm Dùng để làm gì Debug
GetBarAttributes Lấy thông tin resource của BAR BAR type/base/length
Attributes Enable Memory/IO/BusMaster Device decode/DMA
Mem.Read/Write Access MMIO BAR Register access debug
Io.Read/Write Access I/O BAR Legacy I/O
Pci.Read/Write Đọc config space/BAR/Command Config debug
Map/Unmap DMA mapping Bus master device
AllocateBuffer DMA-safe buffer DMA debug
GetLocation BDF của controller Log device đúng

Debug Diary: BAR bằng 0

Triệu chứng:

Device tồn tại
BAR0 read = 0x00000000

Checklist BAR bằng 0

Debug Diary: MMIO đọc toàn 0xFFFFFFFF

Triệu chứng:

BAR có base
MMIO read register -> 0xFFFFFFFF

Checklist MMIO đọc toàn 0xFFFFFFFF

Debug Diary: 64-bit BAR parse sai

Triệu chứng:

BAR0 64-bit
Driver vẫn dùng BAR1 như BAR riêng
Hoặc base address bị truncate

Checklist 64-bit BAR parse sai

Debug Diary: Resource allocation fail vì BAR lớn

Triệu chứng:

Firmware báo out of resources
Large BAR / GPU / accelerator không được assign

Checklist BAR lớn allocation fail

Debug Diary: BAR access OK trong UEFI, fail trong OS

Triệu chứng:

UEFI driver đọc BAR register OK
OS driver đọc fail hoặc device mất

Checklist UEFI OK nhưng OS fail

Anti-pattern khi xử lý BAR

Anti-pattern BAR
Anti-pattern Vì sao sai Cách sửa
Dùng raw BAR làm base Low bits chứa type flags Mask đúng bit
Không handle 64-bit BAR Base/size truncate Ghép low/high và skip BAR tiếp theo
Không check Command Register Device không decode Enable Memory/I/O Space đúng
Chỉ nhìn endpoint BAR Bridge window có thể sai Check toàn path
Probe BAR khi OS sở hữu device Có thể phá resource Chỉ probe trong enumeration hoặc rất cẩn thận
Map MMIO WB bừa Ordering/cache bug Dùng UC/device attr nếu register MMIO
Không check BAR length Access ngoài range Validate offset
Ghi BAR hardcode Resource conflict Dùng allocator/firmware policy

Instrumentation nên có

Instrumentation cho BAR debug
Vị trí Nên log Mục tiêu
PCI enumeration BDF + BAR raw values Biết BAR hiện tại
BAR sizing Type, size, prefetch, 64-bit Debug resource request
Resource allocation Assigned base/length Debug allocation
Bridge windows Memory/prefetch base-limit Debug forwarding
Root bridge aperture MMIO/I/O ranges Debug out of resources
Command Register Before/after bits Debug decode/DMA
PciIo GetBarAttributes BAR attributes Verify firmware view
MMIO access BAR index, offset, width, status Debug register read/write
OS compare UEFI vs OS resource dump Debug handoff
Good/bad diff BAR/resource diff Regression

BAR debug playbook

BAR debug playbook

Security checklist

Security checklist cho BAR/MMIO

Khi đọc BAR log nên tìm gì?

BAR log reading checklist
Cần hiểu Tìm trong log Câu hỏi
BDF Segment:Bus:Device.Function Đúng device không?
Header Type Type 0 hay Type 1 Parse BAR đúng layout không?
BAR raw Raw config value Type bits là gì?
BAR type MMIO/I/O, 32/64-bit Driver xử lý đúng không?
Prefetchable Bit prefetch Window/cache policy đúng không?
Size Sizing result Resource cần bao nhiêu?
Base Assigned address Có non-zero và aligned không?
Bridge window Memory/prefetch window BAR có nằm trong window không?
Command Memory/I/O/BusMaster bits Decode/DMA enable chưa?
Access result MMIO read/write status Fail ở mapping hay device response?

Câu hỏi tự kiểm tra

Tự kiểm tra sau khi đọc note này

Blog seeds

  • BAR trong PCIe là gì?
  • Base Address Register và MMIO giải thích dễ hiểu
  • BAR có value nhưng MMIO đọc fail vì sao?
  • 64-bit BAR trong PCIe debug
  • Bridge window sai làm BAR access không hoạt động

Bài liên quan

Nguồn tham khảo public

Bài viết này hữu ích với bạn?

Bạn có thể chia sẻ cho người đang học firmware, BIOS/UEFI, embedded systems hoặc ủng hộ tác giả.

Góp ý

Nội dung liên quan

Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.

Biến note thành bài viết hoàn chỉnh

Notes là nơi ghi nhanh khái niệm.